I am trying to view the camera stream using QCameraViewfinder in PyQt5. The problem is simple to describe: if the viewfinder has no parent, I can see it, if I set a widget as a parent, I cannot see it.
This code works (I can see a window with the stream from camera):
app = QApplication(sys.argv)
cam = QCamera()
vf = QCameraViewfinder()
cam.setViewfinder(vf)
vf.show()
cam.start()
app.exec_()
This doesn't work (window remains gray):
app = QApplication(sys.argv)
wid = QWidget()
cam = QCamera()
vf = QCameraViewfinder(wid)
cam.start()
cam.setViewfinder(vf)
wid.show()
app.exec_()
I read the documentation, but I did not find anything related to this, probably I have missed something.
What is happening?
your code works after setting cam.viewfinder before cam.start and setting setGeometry() for widget and viewfinder e.g.:
app = QApplication(sys.argv)
wid = QWidget()
wid.setGeometry(20,200,700,600)
cam = QCamera()
vf = QCameraViewfinder(wid)
vf.setGeometry(50,50,600,550)
cam.setViewfinder(vf)
cam.start()
wid.show()
app.exec_()
Related
I have a simple gui that has two radio buttons and an IntCtrl for text entry. Initially, I have the top radio button selected and the IntCtrl disabled (unfortunately, I can't figure out how to set it to blank or "grayed out"):
Relevant code snippet:
def loadSettingsPanel(self):
panel = wx.Panel(self)
self.exposureAutomatic = wx.RadioButton(panel, label="Automatic (1ms)", style=wx.RB_GROUP)
self.exposureManual = wx.RadioButton(panel, label="Manual")
self.exposureValue = wx.lib.intctrl.IntCtrl(panel, style=wx.TE_READONLY)
self.exposureManual.Bind(wx.EVT_RADIOBUTTON, self.onClick)
# Add sizers, etc.
I want to "enable" the IntCtrl area in the onClick method, but I can't figure out how to do this. SetStyle() doesn't seem to have the option clear out the wx.TE_READONLY styling and I'd prefer not to recreate the IntCtrl entirely because then it gets annoying to reshuffle everything in the sizer. If there's some way to do this using a TextCtrl, I'd be happy to switch to that and just do the character filtering manually, but I haven't been able to figure out how to enable/disable those either.
Use the Enable function rather than a style.
import wx
import wx.lib.intctrl
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "Intctrl Demo")
panel = wx.Panel(self)
self.exposureAutomatic = wx.RadioButton(panel, label="Automatic (1ms)", style=wx.RB_GROUP, pos=(50,50))
self.exposureManual = wx.RadioButton(panel, label="Manual", pos=(50,80))
self.ic = wx.lib.intctrl.IntCtrl(panel, -1, pos=(150, 80))
self.ic.Enable(False)
self.Bind(wx.EVT_RADIOBUTTON, self.onClick)
def onClick(self, event):
self.ic.Enable(self.exposureManual.GetValue())
app = wx.App()
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
I am following along this udemy course and in the section where we implement a very simplistic gamepad support, I am unable to make my XBOX One controller work as demonstrated in the lecture. Here is the get_input() script with both keyboard support (which works fine when there is no controller connected) and gamepad support.
//keyboard input
left = keyboard_check(vk_left);
right = keyboard_check(vk_right);
up = keyboard_check(vk_up);
down = keyboard_check(vk_down);
attack = keyboard_check_pressed(vk_shift);
jump = keyboard_check_pressed(vk_space);
jump_held = keyboard_check(vk_space);
block = keyboard_check(ord("Z"));
//controller input
var _dev = 0;
if gamepad_is_connected(_dev) {
var _deadzone = 0.3;
left = gamepad_axis_value(_dev, gp_axislh) < -_deadzone;
right = gamepad_axis_value(_dev, gp_axislh) > _deadzone;
up = gamepad_axis_value(_dev, gp_axislv) < -_deadzone;
down = gamepad_axis_value(_dev, gp_axislv) > _deadzone;
attack = gamepad_button_check_pressed(_dev, gp_face2);
jump = gamepad_button_check_pressed(_dev, gp_face1);
jump_held = gamepad_button_check(_dev, gp_face1);
block = gamepad_button_check(_dev, gp_shoulderr);
}
I know that my gamepad is detected because when I run this code:
var numPads= gamepad_get_device_count();
for(var i = 0; i < numPads; i++;)
{
if(gamepad_is_connected(i)) show_message(string(i) + ": " + gamepad_get_description(i));
}
I get a message saying "0: XInput STANDARD GAMEPAD". However, when I launch the game and try to use the buttons or the joystick, nothing happens. I tried using two different XBOX One controller but I have the same problem. When I try with my gamecube controller connected using a Mayflash GC Controller Adapter on slot 4, it works. Am I missing something specific about XBOX One controllers? I think that in the course the teacher uses an XBOX 360 controller, which I don't have.
Please send help!
I've last month tried to implement Controller support using an XBox One Controller, and I got it working just fine. Also with using gamepad_button_check() and gamepad_axis_value() and the other variables I've used from this link: https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/controls/gamepad%20input/index.html
I use both gamepad_is_supported and gamepad_is_connected in the gamepad code to make sure it has found a gamepad.
It should be possible to work with an XBox One Controller.
So maybe the problem is something out of the box. (e.g. Have you checked the Controller is installed on your PC? Or is the connection only in the Create Event, and that it doesn't update when your controller is plugged in?)
I found that matplotlib's NavigationToolbar2Tk 'configure plot' window is being pulled from widgets.py
for ref: https://matplotlib.org/2.0.2/mpl_examples/pylab_examples/subplot_toolbar_01.pdf
The title for this window is Click on slider to adjust subplot param
Please advice me how to change its icon from default tkinter icon.
self.axleft = toolfig.add_subplot(711)
self.axleft.set_title('Click on slider to adjust subplot param')
self.icon = self.resource_path('icon.ico')
self.axleft.icon_bitmap = ImageTk.PhotoImage(Image.open(self.icon))
self.axleft.wm_iconbitmap(self.icon)
self.axleft.set_navigate(False)
I changed the above code starting in line 1115 in widgets.py. Here self.resource_path is a method I created to find the icon's path.
But getting error as subplots don't have the method wm_icon_bitmap
As #ImportanceOfBeingErnest pointed out.. I had to modify the configure_subplots method in _backend_tk.py. Used the wm_icon_bitmap method for the Toplevel widget.
def configure_subplots(self):
toolfig = Figure(figsize=(6,3))
window = Tk.Toplevel()
icon = self.resource_path('icon.ico')
window.icon_bitmap = ImageTk.PhotoImage(Image.open(icon))
window.wm_iconbitmap(icon)
canvas = type(self.canvas)(toolfig, master=window)
toolfig.subplots_adjust(top=0.9)
canvas.tool = SubplotTool(self.canvas.figure, toolfig)
canvas.draw()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
window.grab_set()
I have a QGraphicsScene that contains multiple custom QGraphicsItems. Each item contains a QGraphicsProxyWidget which itself contains whatever widgets are needed by the business logic. The proxy has a Qt::Window flag applied to it, so that it has a title bar to move it around. This is all working well, except when moving a proxy widget when the view has been scaled.
The user can move around the scene à la google maps, ie by zooming out then zooming in back a little farther away. This is done with calls to QGraphicsView::scale. Items should always be visible no matter the zoom value, so they have the QGraphicsItem::ItemIgnoresTransformations flag set.
What happens when moving a proxyWidget while the view has been scaled is that on the first move event the widget will jump to some location before properly being dragged.
I had this issue with Qt5.7.1, and could reproduce it with PyQt5 as it is simpler to reproduce and hack around, please see the snippet below.
Steps to reproduce:
move the widget around, notice nothing unusual
use the mouse wheel to zoom in or out. The higher the absolute scale, the higher the effect on the issue.
click on the widget, and notice how it jumps on the first moving of the mouse.
Snippet:
import sys
import PyQt5
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsProxyWidget, QGraphicsWidget, QGraphicsObject
global view
global scaleLabel
def scaleScene(event):
delta = 1.0015**event.angleDelta().y()
view.scale(delta, delta)
scaleLabel.setPlainText("scale: %.2f"%view.transform().m11())
view.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
# create main widget
w = QWidget()
w.resize(800, 600)
layout = QVBoxLayout()
w.setLayout(layout)
w.setWindowTitle('Example')
w.show()
# rescale view on mouse wheel, notice how when view.transform().m11() is not 1,
# dragging the subwindow is not smooth on the first mouse move event
w.wheelEvent = scaleScene
# create scene and view
scene = QGraphicsScene()
scaleLabel = scene.addText("scale: 1")
view = QGraphicsView(scene)
layout.addWidget(view)
view.show();
# create item in which the proxy lives
item = QGraphicsWidget()
scene.addItem(item)
item.setFlag(PyQt5.QtWidgets.QGraphicsItem.ItemIgnoresTransformations)
item.setAcceptHoverEvents(True)
# create proxy with window and dummy content
proxy = QGraphicsProxyWidget(item, Qt.Window)
button = QPushButton('dummy')
proxy.setWidget(button)
# start app
sys.exit(app.exec_())
The jump distance is:
proportional to the scaling of the view , and to the distance of the mouse from the scene origin
goes from scene position (0,0) towards the mouse position (I think)
might be caused by the proxy widget not reporting the mouse press/move properly. I'm hinted at this diagnostic after looking at QGraphicsProxyWidgetPrivate::mapToReceiver in qgraphicsproxywidget.cpp (sample source), which does not seem to take scene scaling into account.
I am looking for either
confirmation that this is an issue with Qt and I did not misconfigured the proxy.
an explanation on how fix the mouse location given by the proxy to its children widgets (after installing a eventFilter)
any other workaround
Thanks
Almost 2 years later I got back to this issue again, and finally found a solution. Or rather a workaround, but a simple one at least. It turns out I can easily avoid getting into the issue with local/scene/ignored transforms in the first place.
Instead of parenting the QGraphicsProxyWidget to a QGraphicsWidget, and explicitly setting the QWidget as proxy target, I get the proxy directly from the QGraphicsScene, letting it set the window flag on the wrapper, and set the ItemIgnoresTransformations flag on the proxy. Then (and here's the workaround) I install an event filter on the proxy, intercept the GraphicsSceneMouseMove event where I force the proxy position to currentPos+mouseDelta (both in scene coordinates).
Here's the code sample from above, patched with that solution:
import sys
import PyQt5
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *
global view
global scaleLabel
def scaleScene(event):
delta = 1.0015**event.angleDelta().y()
view.scale(delta, delta)
scaleLabel.setPlainText("scale: %.2f"%view.transform().m11())
view.update()
class ItemFilter(PyQt5.QtWidgets.QGraphicsItem):
def __init__(self, target):
super(ItemFilter, self).__init__()
self.target = target
def boundingRect(self):
return self.target.boundingRect()
def paint(self, *args, **kwargs):
pass
def sceneEventFilter(self, watched, event):
if watched != self.target:
return False
if event.type() == PyQt5.QtCore.QEvent.GraphicsSceneMouseMove:
self.target.setPos(self.target.pos()+event.scenePos()-event.lastScenePos())
event.setAccepted(True)
return True
return super(ItemFilter, self).sceneEventFilter(watched, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
# create main widget
w = QWidget()
w.resize(800, 600)
layout = QVBoxLayout()
w.setLayout(layout)
w.setWindowTitle('Example')
w.show()
# rescale view on mouse wheel, notice how when view.transform().m11() is not 1,
# dragging the subwindow is not smooth on the first mouse move event
w.wheelEvent = scaleScene
# create scene and view
scene = QGraphicsScene()
scaleLabel = scene.addText("scale: 1")
view = QGraphicsView(scene)
layout.addWidget(view)
view.show();
button = QPushButton('dummy')
proxy = scene.addWidget(button, Qt.Window)
proxy.setFlag(PyQt5.QtWidgets.QGraphicsItem.ItemIgnoresTransformations)
itemFilter = ItemFilter(proxy)
scene.addItem(itemFilter)
proxy.installSceneEventFilter(itemFilter)
# start app
sys.exit(app.exec_())
Hoping this may help someone who's ended up in the same dead end I was :)
I am new to osx programming. I am using pyobjc to create the alerts. My understanding of Modal windows or dialogs is that modal windows require the user’s action before they can proceed. However, if I use runModal of NSAlert, I am still able to goto other apps while the alert is still shown. Is my understanding of modal dialogs incorrect.
class Alert(object):
def __init__(self, messageText):
super(Alert, self).__init__()
self.messageText = messageText
self.informativeText = ""
self.buttons = []
def displayAlert(self):
alert = NSAlert.alloc().init()
alert.setMessageText_(self.messageText)
alert.setInformativeText_(self.informativeText)
# alert.setAlertStyle_(NSInformationalAlertStyle)
alert.setAlertStyle_(NSCriticalAlertStyle)
for button in self.buttons:
alert.addButtonWithTitle_(button)
NSApp.activateIgnoringOtherApps_(True)
self.buttonPressed = alert.runModal()
def alert(message="Default Message", info_text="", buttons=["OK"]):
ap = Alert(message)
ap.informativeText = info_text
ap.buttons = buttons
ap.displayAlert()
return ap.buttonPressed
You would not be able to swap to any other apps if the modal dialog was a system modal dialog. In the case of your app, it prevents you from proceeding any further in the user interface of your own application, not in other applications.
In the case of your code, you're creating an application-modal dialog, which is as described in the NSAlert Documentation.