PyQt QtDesigner lost of the windows minimize buttons - windows

My problem is only in Qtdesigner.
I am using QtDesigner v4.8.4 to define my HMI for a pyqt project. In this editor the window I have drown, has got a reduce and a close button in right up corner. I am sorry I wanted to show it to you with screenshots but I don't have enough reputation.
When I use it or previsualize it (with Ctrl + R), I lose the "minimize button" of the window and its functionnality.
Do you have the same behavior?
I have a useless ? button instead and the close button. How could I keep it to minimize my window ?
Thanks a lot for any advice!

When I use it or previsualize it (with Ctrl + R), I lose the "minimize button" of the window and its functionnality.
Answer : This is not bug, I just preview your widget only. If your implement in pyqt can see all button for windows.
Picture: Show previsualize of Qt4 Designer doesn't have "minimize button"
Picture: Show running of PyQt4 (It default have "minimize button")"
Can you please show an example of implementation of the minimize button of the up right corner because for my script
OK, Keyword is implement event in widget by this method QWidget.changeEvent (self, QEvent)
, Please see my example code, Hope is helps;
import sys
from PyQt4 import QtCore, QtGui, uic
(loadUserInterface, loadQWidget) = uic.loadUiType('QWelcomeWidget.ui')
class QWelcomeWidget (loadQWidget):
def __init__ (self, parent = None):
loadQWidget.__init__(self, parent)
self.ui = loadUserInterface()
self.ui.setupUi(self)
def changeEvent (self, eventQEvent):
if eventQEvent.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
print 'Window Minimized'
QtGui.QWidget.changeEvent(self, eventQEvent)
if __name__ == '__main__':
appQApplication = QtGui.QApplication(sys.argv)
mainQWidget = QWelcomeWidget()
mainQWidget.show()
# Start Application
sys.exit(appQApplication.exec_())
References : http://pyqt.sourceforge.net/Docs/PyQt4/qwidget.html#changeEvent
Regards,

convert your .ui file to (.py)python file using
pyuic4 filename.ui
sudo pyuic4 -x ptqt_filename.ui -o python_file_name.py
Now run that python file,you will be able to see all controls
python pyqt_first_ui.py

Related

QDialog not centered on parent QMainWindow on Ubuntu 22.04

I encountered a strange situation on Ubuntu 22.04, using PySide6 when spawning a QDialog from a QMainWindow parent via menu action, like with the sample code below:
from PySide6.QtWidgets import QApplication, QMainWindow, QDialog
from PySide6.QtGui import QAction
class Dialog(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setGeometry(0, 0, 500, 500)
menu = self.menuBar()
submenu = menu.addMenu("Submenu")
self.action_open_dialog = QAction("Open Dialog", self)
self.action_open_dialog.setCheckable(False)
self.action_open_dialog.triggered.connect(self.open_dialog)
submenu.addAction(self.action_open_dialog)
def open_dialog(self):
dialog = Dialog(self)
dialog.exec()
if __name__ == '__main__':
app = QApplication()
w = MainWindow()
w.show()
app.exec()
The position of the dialog should be centered on the main window as parent, according to the documentation, but this is not the case. In fact, the dialogs initial position can even be outside the main window when the latter is moved before spawning the dialog, and appears to be located at some fixed screen position on the upper left. Curiously, the dialog is properly appearing in the center of the main window when executing on a Windows system.
Is this a known issue with Linux systems and is there some way to force the dialog to appear in the main windows center?
PS: The Ubuntu OS is executed as a VM on VirtualBox, in case this is relevant.
PPS: As requested, the exact Ubuntu version is 22.04.1 and the Wayland (ie. mutter) version is 42.0-3ubuntu2 - this is really just a stock install straight from the downloaded ISO without any modifications.
With Glade 3.38.2 "Centre on Parent" for modal popup gtkWindows works perfect in XORG, but not in Wayland.
In Wayland you have to select Toplevel as type under Window Attributes. With popup only position = mouse works.
As this is a Wayland problem, the same may be the case for QT.

How can I dynamically add actions to a QMenu while it is open on a Mac?

I have QSystemTrayIcon with a QMenu. In order to fill the menu, I need to fetch some things from the network, so I want to do that in the background.
So I have a QThread with a slot that is connected to the activated signal of the tray icon. Then the thread fetches the resources and updates the menu using another signal.
However, these updates do not show until I close and reopen the menu.
This seems to be a Mac specific problem. I ran my code on Windows, and there it updated more or less correctly. Is there any workaround?
Below is an extracted version of the problem. When the menu is opened, it will sleep 1 second in a thread and then change the menu. This change is not seen.
import sys
import time
from PySide import QtCore, QtGui
class PeerMenu(QtGui.QMenu):
def __init__(self):
QtGui.QMenu.__init__(self)
self.set_peers("prestine")
#QtCore.Slot(object)
def set_peers(self, label):
self.clear()
self.addAction(QtGui.QAction(label, self))
self.addSeparator()
self.addAction(QtGui.QAction("Hello", self))
class GUIListener(QtCore.QObject):
files = QtCore.Signal(object)
def __init__(self):
QtCore.QObject.__init__(self)
self.counter = 0
#QtCore.Slot()
def check(self):
time.sleep(1)
self.counter += 1
self.files.emit(str(self.counter))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
icon = QtGui.QSystemTrayIcon(QtGui.QIcon('images/glyphicons-206-electricity.png'), app)
listener = GUIListener()
t = QtCore.QThread()
t.start()
listener.moveToThread(t)
menu = PeerMenu()
icon.activated.connect(listener.check)
listener.files.connect(menu.set_peers)
icon.setContextMenu(menu)
icon.show()
app.exec_()
After a few hours of extensive googling I finally figured it out.
You can create a borderless window using QtGui.QMainWindow(parent=None, flags=QtCore.Qt.Popup) and then find the location of the icon with icon.geometry().center() and finally move the window there with window.move(icon_point).
There is some hackery involved in deciding how to place the window relative to the icon. Full code can be found at https://github.com/pepijndevos/gierzwaluw/blob/master/gui.py

wxPython Mouse Entering/Leaving event methods don't work on Linux

I am trying to provide a custom button class that needs a hover for it to work properly. I am therefore using StaticBitmap and extending it. But I am finding differences between Windows and Linux using the same exact code between both. The following small simple example doesn't work properly in Linux, but works fine in Windows:
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Test")
panel = wx.Panel(self, wx.ID_ANY, size=(200,100))
panel.SetBackgroundColour("Black")
# create a normal bitmap button
bitmap = wx.Bitmap("images/power.png", wx.BITMAP_TYPE_ANY)
self.image1 = wx.StaticBitmap(panel, bitmap=bitmap, size=bitmap.GetSize())
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.image1)
panel.SetSizer(sizer)
# This works on Windows, but not on Linux
#self.image1.Bind(wx.EVT_ENTER_WINDOW, self.OnHover)
#self.image1.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveHover)
# This (used by itself) gets events for both Linux/Win, but
# doesn't find e.Entering() or e.Leaving() on Linux!
self.image1.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents)
def OnHover(self, e):
print "Hover"
def OnLeaveHover(self,e):
print "Leaving Hover"
def OnMouseEvents(self,e):
print "Mouse event"
#print dir(e)
if e.Entering():
print "Hover"
elif e.Leaving():
print "Leaving Hover"
else:
e.Skip()
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
Is this a known issue? Is there some other way to bind the event to get the mouseover/hover operation to work properly in Linux?
Also, no forms of self.Bind() work here on Linux or Windows. Why? i.e.:
self.Bind(wx.EVT_ENTER_WINDOW, self.OnHover, self.image1)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveHover, self.image1)
Hmmm..., all I can tell you is what I experienced with your code when using it in Ubuntu 12.04
1) My picture never shows up (i.e. a grey window nothing more)
2) when binding the EVT_ENTER/LEAVE_WINDOW to self and not to image1 (see below), it works
# This now works on Linux
#self.Bind(wx.EVT_ENTER_WINDOW, self.OnHover)
#self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveHover)
I hope this helps you in some form. Also I would like to add that I have made many a bad experience with cross-platform compatibility of wxpython unfortunately. I like the library a lot, but once it delves into more obscure widgets, the behaviour may differ wildly between Windows and Linux.
I remember trying to use the MPlayerCtrl once and for the same method in Windows it would return 0 while in Linux it would return -1 (can't mind exactly which method it was, that project got dumped once I noticed it)
Maybe, this is another one of those strange behaviours...
Having thought about it some more.
instead of binding the event to the picture, you could bind it to the widget it is displayed in, such as your panel.
self.panel = wx.Panel(self, wx.ID_ANY, size=(200,100))
self.panel.SetBackgroundColour("Black")
...
#self.panel.Bind(wx.EVT_ENTER_WINDOW, self.OnHover)
#self.pane.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveHover)
you should bind the wx.EVT_ENTER_WINDOW/wx.EVT_LEAVE_WINDOW event to self.panel. that works.
wx.EVT_ENTER_WINDOW/wx.EVT_LEAVE_WINDOW is not the subclass of wx.CommandEvent class. It isn't thrown up to the parent window to process.

wxWidgets dialog doesn't get a maximize box

I've got a wxPython (via wxGlade) app with a dialog that has wx.MAXIMIZE_BOX set in the style, but the maximize box doesn't appear when I run the app.
Here's a minimal program that exhibits the behavior:
#!/usr/bin/env python
import wx
class MyDialog(wx.Dialog):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.MAXIMIZE_BOX
wx.Dialog.__init__(self, *args, **kwds)
self.SetTitle("dialog_1")
self.Layout()
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
dialog_1 = MyDialog(None, -1, "")
app.SetTopWindow(dialog_1)
dialog_1.Show()
app.MainLoop()
Note that wx.MAXIMIZE_BOX is set, but when I run this program I don't get a maximize box on the dialog:
Is this a window manager issue?
Is there something I can do to make the maximize box show up? (My real dialog has a bunch of scrolled text from a log file and it's easier to click maximize than it is to manually resize to fill the screen.)
I'm using:
Linux (Ubuntu 10.04 LTS)
python-wxgtk, libwxgtk2.8-0, libwxbase2.8-0: 2.8.10.1-0ubuntu1.2
metacity: 1:2.30.1-0ubuntu1.1
I found this in the wxWidgets docs:
"Under Unix or Linux, MWM (the Motif Window Manager) or other window managers recognizing the MHM hints should be running for any of these styles ( including wxMAXIMIZE_BOX ) to have an effect."
So it sounds like it might well be a window manager issue.

Create a PyGTK GUI with event to reload itself

I'm prototyping GUI layout with PyGTK, sometimes using glade/builder sometimes not, and the following scene repeats endlessly:
Modify the code
Run the GUI script
Judge the result
Modify again
Run again...
So, since I heard that Python allows reloading of modules, I would like to know if it is possible to modify the code WITHOUT CLOSING THE WINDOW, and then, from the window itself, say, clicking on a button, "reload" the window reflecting the changes in code.
Since it is a conceptual question, I don't have any specific code to show.
Thanks for the attention
I think it is possible if you do the following:
Identify and isolate the widget W that you want to see updated when you press the button (if you want to see the whole window updated, then make it whatever you add in the window, not the window itself).
Write a function (or class) that creates and returns this widget
Put this function or class in a module that you will reload
Create your button outside W and connect it to a function that does the following
Remove current W from window
Reload the module
Create new instance of W
Add it to the window
Of course, the critical step here is "reload the module". I guess you have to make sure no code from the module is running and no other module depends on variables defined on this module.
EDIT: I had some time, so I made a little prototype. Change the label in widget_module.py and then hit Update
gui.py
# Load in pygtk and gtk
import pygtk
pygtk.require('2.0')
import gtk
import widget_module
# Define the main window
class Whc:
def __init__(self):
# Window and framework
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("destroy", self.destroy)
# A Button, with an action
# Add it to the geometry
# show the button
self.button = gtk.Button("Update")
self.button.connect("clicked", self.update, None)
self.vbox = gtk.VBox()
self.vbox.pack_start(self.button)
self.widget = widget_module.get_widget()
self.vbox.pack_start(self.widget)
self.window.add(self.vbox)
# Show the window
self.window.show_all()
# Callback function for use when the button is pressed
def update(self, widget, data=None):
print "Update"
self.vbox.remove(self.widget)
reload(widget_module)
self.widget = widget_module.get_widget()
self.vbox.pack_start(self.widget)
self.widget.show()
# Destroy method causes appliaction to exit
# when main window closed
def destroy(self, widget, data=None):
gtk.main_quit()
# All PyGTK applicatons need a main method - event loop
def main(self):
gtk.main()
if __name__ == "__main__":
base = Whc()
base.main()
widget_module.py
import pygtk
import gtk
def get_widget():
return gtk.Label("hello")

Resources