PyQt5: count seconds mouse is over QPushButton in tooltip - python-3.x

The following running code gives a window with a button on it . The tooltip displays when the mouse enters the button.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtTest import QTest
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout()
self.button = QPushButton("MyButton")
global i
i = 0
self.button.setToolTip(str(i) + " seconds has passed since you move your mouse onto MyButton")
self.button.leaveEvent = self.clear()
self.layout.addWidget(self.button)
timer = QTimer(self)
timer.timeout.connect(self.start_counting)
timer.start(1000)
self.widget = QWidget()
self.widget.setLayout(self.layout)
self.setCentralWidget(self.widget)
def clear(self):
global i
i = 0
def start_counting(self):
if self.button.underMouse() == True:
global i
i = i + 1
self.button.setToolTip(str(i) + " seconds has passed since you move your mouse onto MyButton")
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_() )
My goal is to count the number of seconds the mouse is inside the button and live display it using the tooltip. More precisely, I need to make sure all of the following is happening:
Every time the mouse enters the button, the count starts at 0 seconds and the tooltip shows up.
While the mouse stays inside the button (stationary or moving), the tooltip stays shown with the number of seconds (the text displayed inside the tooltip) updated over time.
When the mouse leaves the button, the count is cleared to zero.
As seen in the code, I have attempted to use underMouse to achieve my goals. My attempt is a partial success as the tooltip does update itself when the mouse moves inside the button. However, the tooltip does not update itself when the mouse stays stationary inside the button. Also, the count does not seem to be cleared when the mouse moves outside of the button .
What am I missing ?

One solution is to use an event-filter to monitor the enter and leave events, and also use an elapsed-timer to get an accurate measure of how long the mouse has been over the target widget. Below is a basic demo based on your example that implements the above. It also tries to match the normal behaviour of tooltips, but if necessary you can easily adjust the code to suit your own needs:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout()
self.button = QPushButton("MyButton")
self.layout.addWidget(self.button)
self.widget = QWidget()
self.widget.setLayout(self.layout)
self.setCentralWidget(self.widget)
self.position = QPoint()
self.counter = QElapsedTimer()
self.timer = QTimer()
self.timer.timeout.connect(self.start_counting)
self.button.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.Enter and source is self.button:
self.counter.start()
self.timer.start(1000)
QTimer.singleShot(500, self.start_counting)
elif event.type() == QEvent.Leave and source is self.button:
self.timer.stop()
QToolTip.hideText()
return super().eventFilter(source, event)
def start_counting(self):
if self.button.underMouse():
if not QToolTip.isVisible():
self.position = QCursor.pos()
count = int(self.counter.elapsed() / 1000)
QToolTip.showText(self.position, (
f'{count} seconds have passed since '
'you moved your mouse onto MyButton'
))
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_() )

Related

How to use QStackedWidget()

Am trying to use QStackedWidget() to switch to my next window but when i do that i get some errors that don't have when i run my ".py" files separately.
what my app should do is ... activate my group box with a click, then if i click the button, a new transparent window should pop-up with a mouse-cross listener, then when you click something it should stops returning the mouse cursor to normal and closing the transparent window.
window1.py
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QColor, QKeySequence, QIcon, QCursor
from window2 import *
class Ui_Form(QtWidgets.QWidget):
def __init__(self):
super(Ui_Form, self).__init__()
##if i use this method, it does not show my transparent window, also it shows an error that i dont get when run it separately.
def goToTransparentWindowMethod(self):
self.goToTransparentWindow = TransparentWindowClass()
myWindow.addWidget(self.goToTransparentWindow)
myWindow.setCurrentIndex(myWindow.currentIndex()+1)
def setupUi(self, myWindow):
myWindow.setObjectName("myWindow")
myWindow.resize(627, 327)
self.horizontalLayoutWidget = QtWidgets.QWidget(myWindow)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 300, 270))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.gpb_main = QtWidgets.QGroupBox(self.horizontalLayoutWidget)
self.gpb_main.setCheckable(True)
self.gpb_main.setChecked(False)
self.gpb_main.setObjectName("gpb_spell_main")
self.btn_main = QtWidgets.QPushButton(self.gpb_main)
self.btn_main.setGeometry(QtCore.QRect(10, 40, 88, 27))
self.btn_main.setObjectName("btn_main")
self.btn_main.clicked.connect(self.goToTransparentWindowMethod)
self.horizontalLayout.addWidget(self.gpb_main)
self.retranslateUi(myWindow)
QtCore.QMetaObject.connectSlotsByName(myWindow)
def retranslateUi(self, myWindow):
_translate = QtCore.QCoreApplication.translate
myWindow.setWindowTitle(_translate("myWindow", "Window1"))
self.gpb_main.setTitle(_translate("myWindow", "example"))
self.btn_main.setText(_translate("myWindow", "click me"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
myWindow = QtWidgets.QStackedWidget()
ui = Ui_Form()
ui.setupUi(myWindow)
myWindow.show()
sys.exit(app.exec_())
window2.py
from PyQt5 import QtCore, QtGui, QtWidgets
from pynput.mouse import Listener
import pyautogui
class TransparentWindowThreadClass(QtCore.QObject):
def __init__(self, parent=None):
super(TransparentWindowThreadClass, self).__init__()
#QtCore.pyqtSlot()
def on_click_main(self, x, y, button, pressed):
try:
if pressed:
self.pos_main = pyautogui.position()
self.get_rgb_main = pyautogui.pixel(self.pos_main[0], self.pos_main[1])
r = self.get_rgb_main.red
g = self.get_rgb_main.green
b = self.get_rgb_main.blue
self.get_rgb_main = r,g,b
Transparent_Window.unsetCursor()#error here when is called from window1
Transparent_Window.close()#error here when is called from window1
#Pressed
self.pressed_Msg = 'Pressed at x:{0} y:{1} RGB:{2}'.format(x, y, self.get_rgb_main)
print(self.pressed_Msg)
else:
#Released msg
self.released_Msg = 'Released at x:{0} y:{1} RGB:{2}'.format(x, y, self.get_rgb_main)
print(self.released_Msg)
if not pressed:
return False
except KeyboardInterrupt:
print('you pressed ctrl+c')
except NameError:
print("Error on_click_main")
except RuntimeError:
print('run time error')
except TypeError:
print('ype error')
except AttributeError:
print('Attribute Error')
#QtCore.pyqtSlot()
def loop_onclick_listener(self):
try:
with Listener(on_click=self.on_click_main) as listener:
listener.join()
except KeyboardInterrupt:
print('you pressed ctrl+c')
except NameError:
print("Error onclick_listener")
except RuntimeError:
print('run time error')
except TypeError:
print('ype error')
except AttributeError:
print('Attribute Error')
class TransparentWindowClass(QtWidgets.QWidget):
def __init__(self, parent=None):
super(TransparentWindowClass, self).__init__()
self.monitorResolution = pyautogui.size()
# create a QThread and start the thread that handles
self.thread = QtCore.QThread()
self.thread.start()
# create the worker without a parent so you can move it
self.worker = TransparentWindowThreadClass()## my custom thread class
# the worker is moved to another thread
self.worker.moveToThread(self.thread)
# if the thread started, connect it
self.thread.started.connect(self.worker.loop_onclick_listener)
def setupUi(self, Transparent_Window):
Transparent_Window.setObjectName("Transparent_Window")
Transparent_Window.resize(self.monitorResolution[0], self.monitorResolution[1])
Transparent_Window.setWindowFlags(QtCore.Qt.FramelessWindowHint)
Transparent_Window.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
Transparent_Window.setCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
self.retranslateUi(Transparent_Window)
QtCore.QMetaObject.connectSlotsByName(Transparent_Window)
def retranslateUi(self, Transparent_Window):
_translate = QtCore.QCoreApplication.translate
Transparent_Window.setWindowTitle(_translate("Transparent", "Transparent Window"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Transparent_Window = QtWidgets.QWidget()
ui = TransparentWindowClass()
ui.setupUi(Transparent_Window)
Transparent_Window.show()
sys.exit(app.exec_())
You are making things too complex.
Also, even assuming that no other possible solution could be used, you must remember that widgets are not thread-safe, and can not be directly accessed from external threads. The only safe and correct way to communicate between threads is by using signals and slots.
That said, there is no need for pyautogui nor pynput if you just want to get the color of a pixel on the screen.
If you want to grab a pixel on the screen, you can use the QScreen function grabWindow(), using 0 as window id (which matches the whole screen), and with a single-pixel area.
Then you can use grabMouse() to ensure that you always receive mouse events, even if the mouse is outside of the widget and no mouse button was being pressed. Note that grabMouse() can only work on visible widgets, so we need to "hide" the window by moving it off-screen.
Then, overriding mousePressEvent() you can use grabWindow() with the global position of the mouse, it will return a QPixmap that can be converted to a QImage and get the pixelColor() of the grab above.
The grabbing can be canceled by pressing Esc.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class GrabTest(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 200)
self.button = QPushButton('Grab!')
self.colorLabel = QLabel('No color', alignment=Qt.AlignCenter)
self.colorLabel.setFixedSize(120, 30)
self.colorLabel.setStyleSheet('border: 1px solid black;')
layout = QVBoxLayout(self)
layout.addStretch()
layout.addWidget(self.button, alignment=Qt.AlignCenter)
layout.addWidget(self.colorLabel, alignment=Qt.AlignCenter)
layout.addStretch()
self.button.clicked.connect(self.startGrab)
def mousePressEvent(self, event):
if QWidget.mouseGrabber() == self:
self.getPixel(event.globalPos())
else:
super().mousePressEvent(event)
def keyPressEvent(self, event):
if QWidget.mouseGrabber() == self and event.key() == Qt.Key_Escape:
self.stopGrab()
else:
super().keyPressEvent(event)
def startGrab(self):
self.grabMouse(Qt.CrossCursor)
self.oldPos = self.pos()
deskRect = QRect()
for screen in QApplication.screens():
deskRect |= screen.geometry()
# move the window off screen while keeping it visible
self.move(deskRect.bottomRight())
def stopGrab(self):
self.releaseMouse()
self.move(self.oldPos)
def getPixel(self, pos):
screen = QApplication.screens()[0]
pixmap = screen.grabWindow(0, pos.x(), pos.y(), 1, 1)
color = pixmap.toImage().pixelColor(0, 0)
if color.lightnessF() > .5:
textColor = 'black'
else:
textColor = 'white'
self.colorLabel.setStyleSheet('''
color: {};
background: {};
'''.format(textColor, color.name()))
self.colorLabel.setText(color.name())
self.stopGrab()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
grabber = GrabTest()
grabber.show()
sys.exit(app.exec())

PyQt5 - How to return application to initial state after error handling with QMessageBox

Just starting out with Python3 and PyQt5 and I'm kinda stuck here.
My main window takes two ticker codes as input and, after the user presses the Show Me! button, outputs ratio averages for each of them. I created a QMessageBox with an OK button that pops up when the user enters invalid ticker codes.
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import good_morning as gm
import MainUI
class MainWindow(QMainWindow, MainUI.Ui_MyStockratios):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.home()
def home(self):
#If Show Me! button is clicked, go grab_user_input()
self.show_me_btn.clicked.connect(self.grab_user_input)
def grab_user_input(self):
#Grab user input for QLineEdits
self.ticker1_value = self.ticker1_label.text()
self.ticker2_value = self.ticker2_label.text()
#Fetch the ratios and place them in a dataframe
self.kr = gm.KeyRatiosDownloader()
try:
self.kr_frame1 = self.kr.download(self.ticker1_value)
self.kr_frame2 = self.kr.download(self.ticker2_value)
#Error handling
except ValueError:
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("Invalid ticker code")
msg.setInformativeText("Please verify the data you entered and try again.")
msg.setWindowTitle("Error")
msg.setStandardButtons(QMessageBox.Ok)
reply = msg.exec_()
if reply:
self.ticker2_label.clear()
self.ticker1_label.clear()
self.home()
[...]
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
if __name__ == "__main__":
main()
Here's my problem: I want the application to return to its' initial state after the user presses the QMessageBox's OK button, which means the QLineEdits must be cleared and the application must wait for the user to input new data and press the Show Me! button again. I cleared the QLineEdits with the clear() function, but can't seem to make the application wait for new user input.
Thanks in advance !
For future reference you're posted code is a bit incomplete. I took some liberties to get a working example. You can ignore most of the changes except for the button handler part. You only need to connect the button once. Your home() method is not needed.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
# import good_morning as gm
# import MainUI
class MainWindow(QMainWindow):#, MainUI.Ui_MyStockratios):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# self.setupUi(self)
layout = QVBoxLayout()
widget = QWidget(self)
self.setCentralWidget(widget)
widget.setLayout(layout)
self.show_me_btn = QPushButton('Show Me!', self)
layout.addWidget(self.show_me_btn)
self.ticker1_label = QLineEdit(self)
layout.addWidget(self.ticker1_label)
self.ticker2_label = QLineEdit(self)
layout.addWidget(self.ticker2_label)
# self.home()
self.show_me_btn.clicked.connect(self.grab_user_input)
# def home(self):
# #If Show Me! button is clicked, go grab_user_input()
# self.show_me_btn.clicked.connect(self.grab_user_input)
def grab_user_input(self):
#Grab user input for QLineEdits
self.ticker1_value = self.ticker1_label.text()
self.ticker2_value = self.ticker2_label.text()
# #Fetch the ratios and place them in a dataframe
# self.kr = gm.KeyRatiosDownloader()
#
# try:
# self.kr_frame1 = self.kr.download(self.ticker1_value)
# self.kr_frame2 = self.kr.download(self.ticker2_value)
#
# #Error handling
# except ValueError:
if 1:
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("Invalid ticker code")
msg.setInformativeText("Please verify the data you entered and try again.")
msg.setWindowTitle("Error")
msg.setStandardButtons(QMessageBox.Ok)
reply = msg.exec_()
if reply:
self.ticker2_label.clear()
self.ticker1_label.clear()
# self.home()
# [...]
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
if __name__ == "__main__":
main()

PyQt5 - Can QTabWidget content extend up to Main Window edges, even with no content?

I am new to PyQt5... Simple question here.
I am using PyQt5 to build a simple application. This application has a Main Window containing a QTabWidget with 3 tabs. Once the application starts, all tab pages are empty and get filled later on. When tab pages are empty, I would still like them to appear as blank pages and extend up to the Main Window edges.
I've been trying to achieve this in two ways: using a layout and using the setGeometry function. Yet the tab pages never extend vertically very far, and horizontally they never go beyond the last tab. See code below.
import sys
from PyQt5.QtWidgets import *
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Window With Tabs")
self.setGeometry(50,50,400,400)
oTabWidget = QTabWidget(self)
oPage1 = QWidget()
oLabel1 = QLabel("Hello",self)
oVBox1 = QVBoxLayout()
oVBox1.addWidget(oLabel1)
oPage1.setLayout(oVBox1)
oPage2 = QWidget()
oPage2.setGeometry(0,0,400,400)
oPage3 = QWidget()
oPage3.setGeometry(0,0,400,400)
oTabWidget.addTab(oPage1,"Page1")
oTabWidget.addTab(oPage2,"Page2")
oTabWidget.addTab(oPage3,"Page3")
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
oMainwindow = MainWindow()
sys.exit(app.exec_())
Any idea how to modify the code so the empty pages will extend up to the edges of Main Window ?
Set a layout on the main widget:
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Window With Tabs")
self.setGeometry(50,50,400,400)
layout = QVBoxLayout(self)
oTabWidget = QTabWidget(self)
layout.addWidget(oTabWidget)
The setGeometry calls on the other widgets are redundant.
import sys
from PyQt5.QtWidgets import *
class MainWindow(QWidget):
# window object
def __init__(self):
super().__init__()
self.initGUI() # call custom code
def initGUI(self):
self.setWindowTitle("Window With Tabs") # window...
self.setGeometry(50,50,400,400) #...properties
TabW=self.createTabs() # a custom-tab object
layout = QVBoxLayout(self) # main window layout
layout.addWidget(TabW) #populate layout with Tab object
self.show() # display window
def createTabs(self): # create and return Tab object
oPage1 = QWidget() # tabs...
oPage2 = QWidget()
oPage3 = QWidget()
oTabWidget = QTabWidget() # Tabobject
oTabWidget.addTab(oPage1,"Page1") # populate tab object...
oTabWidget.addTab(oPage2,"Page2")
oTabWidget.addTab(oPage3,"Page3")
return oTabWidget # return tab object
if __name__ == "__main__": # Rest is History!
app = QApplication(sys.argv)
oMainwindow = MainWindow()
sys.exit(app.exec_())

How do I thread a single method on a PyQt GUI so that the rest of the GUI is still accessible?

Basically, when the Switch Button is pressed, which is connected to the reconfigure method, I want everything in the reconfigure method to run as a separate thread/process so the main GUI is still accessible and not being blocked. Below is a watered down version of my code.
import sys, time
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import *
#//Popup Class - Will appear when the Switch Button is pressed
class Popup(QWidget):
def __init__(self):
QWidget.__init__(self)
#//nothing here now, it will have a message telling user to wait while program is run
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
grid = QtGui.QGridLayout()
label_header = QtGui.QLabel("TEST RECONFIGURE")
font = label_header.font()
font.setPointSize(24)
label_header.setFont(font)
#//Creating Static Labels that will be placed in the GUI
label_1 = QtGui.QLabel("Menu 1:")
label_2 = QtGui.QLabel("Menu 2:")
label_spacer = QtGui.QLabel("")
label_cfg = QtGui.QLabel("Current Configuration: '/tmp/directory_here' ")
global comboBox1
comboBox1 = QtGui.QComboBox()
comboBox1.addItem("1")
comboBox1.addItem("2")
global comboBox2
comboBox2 = QtGui.QComboBox()
comboBox2.addItem("3")
comboBox2.addItem("4")
#//Switch Button!!!
global switchButton
switchButton = QPushButton("Switch")
switchButton.clicked.connect(self.reconfigure)
quitButton = QtGui.QPushButton('Quit')
quitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
#//Configure the grid layout
grid.addWidget(label_spacer, 0,0,9,9)
grid.addWidget(label_header, 0,0,1,6)
grid.addWidget(label_1, 1,0,1,1)
grid.addWidget(comboBox1, 2,0,1,1)
grid.addWidget(label_2, 3,0,1,1)
grid.addWidget(comboBox2, 4,0,1,1)
grid.addWidget(switchButton, 5,0,1,2)
grid.addWidget(label_cfg, 6,0,1,9)
grid.addWidget(quitButton, 9,9,1,1)
self.setLayout(grid)
self.setGeometry(640,300,400,600)
self.show()
#//open up the popup window for switch button, and reconfigure
def reconfigure(self):
print "Opening New Window"
self.w = Popup()
self.w.setGeometry(QRect(self.x()+100,self.y()+100,400,200))
self.w.show()
txt1 = str(comboBox1.currentText())
txt2 = str(comboBox2.currentText())
print " reconfiguring to option %s and option %s" %(txt1, txt2)
#
# This is where most of the work is done, and takes about 1/2 an hour for everything to run
# Want to make this method a separate thread/process so the rest of the main GUI is still accessible
# while the program is running as the whole class will be a separate tab in a larger GUI
#
print "all done!"
#//runner
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I feel like I have to use threading and signals to accomplish this, but I am not having much luck. Any help would be greatly appreciated. Thank you!
import sys, time
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import *
class ConfigureThread(QtCore.QThread):
def run(self):
pass
#
# This is where most of the work is done, and takes about 1/2 an hour for everything to run
# Want to make this method a separate thread/process so the rest of the main GUI is still accessible
# while the program is running as the whole class will be a separate tab in a larger GUI
#
#//Popup Class - Will appear when the Switch Button is pressed
class Popup(QWidget):
def __init__(self):
QWidget.__init__(self)
#//nothing here now, it will have a message telling user to wait while program is run
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
grid = QtGui.QGridLayout()
label_header = QtGui.QLabel("TEST RECONFIGURE")
font = label_header.font()
font.setPointSize(24)
label_header.setFont(font)
#//Creating Static Labels that will be placed in the GUI
label_1 = QtGui.QLabel("Menu 1:")
label_2 = QtGui.QLabel("Menu 2:")
label_spacer = QtGui.QLabel("")
label_cfg = QtGui.QLabel("Current Configuration: '/tmp/directory_here' ")
global comboBox1
comboBox1 = QtGui.QComboBox()
comboBox1.addItem("1")
comboBox1.addItem("2")
global comboBox2
comboBox2 = QtGui.QComboBox()
comboBox2.addItem("3")
comboBox2.addItem("4")
#//Switch Button!!!
global switchButton
switchButton = QPushButton("Switch")
switchButton.clicked.connect(self.reconfigure)
quitButton = QtGui.QPushButton('Quit')
quitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
#//Configure the grid layout
grid.addWidget(label_spacer, 0,0,9,9)
grid.addWidget(label_header, 0,0,1,6)
grid.addWidget(label_1, 1,0,1,1)
grid.addWidget(comboBox1, 2,0,1,1)
grid.addWidget(label_2, 3,0,1,1)
grid.addWidget(comboBox2, 4,0,1,1)
grid.addWidget(switchButton, 5,0,1,2)
grid.addWidget(label_cfg, 6,0,1,9)
grid.addWidget(quitButton, 9,9,1,1)
self.setLayout(grid)
self.setGeometry(640,300,400,600)
self.show()
#//open up the popup window for switch button, and reconfigure
def reconfigure(self):
print("Opening New Window")
self.w = Popup()
self.w.setGeometry(QRect(self.x()+100,self.y()+100,400,200))
self.w.show()
txt1 = str(comboBox1.currentText())
txt2 = str(comboBox2.currentText())
print(" reconfiguring to option %s and option %s" %(txt1, txt2))
self.th = ConfigureThread()
self.th.finished.connect(self.configuring_done)
self.th.start()
def configuring_done(self):
print("all done!")
#//runner
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

PyQt4 Mdi sub window not resizing properly

In the following example, when you click the button, the entire form is rebuilt adding a new label each time. At the end is a resize call that doesn't appear to work. While debugging, I validated the sizeHint() is returning the correct dimensions, and internally the widget thinks it is the correct size, but what is drawn is not correct. What can I do to force the MDI window to resize correctly? Also of note, when not sized correctly, if you manually start resizing, it suddenly snaps to the appropriate size.
import sys
import os
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import PyQt4.Qt
class MdiWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.count = 0
self.buildWindow()
def buildWindow(self):
main = QVBoxLayout()
button = QPushButton('Change Count')
button.clicked.connect(self.changeCount)
main.addWidget(button)
for i in range(self.count):
main.addWidget(QLabel(str(i)))
widget = QWidget()
widget.setLayout(main)
self.setCentralWidget(widget)
self.resize(main.sizeHint())
def changeCount(self, event):
self.count += 1
self.buildWindow()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Resize Test')
self.mdiArea = QMdiArea()
self.setCentralWidget(self.mdiArea)
child = MdiWindow()
self.mdiArea.addSubWindow(child)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())

Resources