Here is my code
app = QApplication(sys.argv)
loginWindow = loadUi('~/mainwindow.ui')
okconnect = loadUi('~/okconnect.ui')
def prueba2(test):
print(test + " Testing2")
def prueba(test):
print (test)
okconnect.show()
okconnect.getvmsButton.clicked.connect(lambda: prueba2(test))
loginWindow.show()
loginWindow.connectButton.clicked.connect(lambda: prueba("test"))
sys.exit(app.exec_())
When I press "connect" button, a new window is opened, with a button, "getvmsButton", when I press this button, its show in console the print line in def prueba2(test), but if I close the window, and then I click again in connect button, the window open again and "getvmsButton" is pressed again, the console show 2 messages instead of 1. If I repeat the process, more messages are showed.
What should I change to show only one messages when I close and open several times the window?
When you close your GUI by 'x' doesn't mean you disconnected the button click signal, therefore, every time you click the 'connect' button, the loginWindow will create a new button.clicked event and keep the old ones. A quick solution to this is to define a close-event for the 'x' clicks. Here provided is just a way to close the old signal events.
from PyQt5.QtWidgets import QWidget
OKConnect(QWidget):
def __init__(self):
super().__init__()
self.okconnect = loadUi('~/okconnect.ui')
self.okconnect.closeEvent = self.closeEvent
def closeEvent(self, event):
print("testing2 closing")
# to close the old getvmsButton signals
self.okconnect.getvmsButton.disconnect()
# Here below is exactly your code
app = QApplication(sys.argv)
loginWindow = loadUi('~/mainwindow.ui')
okconnect = OKConnect()
def prueba2(test):
print(test + " Testing2")
def prueba(test):
print (test)
okconnect.show()
okconnect.getvmsButton.clicked.connect(lambda: prueba2(test))
loginWindow.show()
loginWindow.connectButton.clicked.connect(lambda: prueba("test"))
sys.exit(app.exec_())
I am not sure about your .ui files, the code may not work on yours.
Related
I use tkinter and CTK:
I have created a page for login and I want to stop or use this page when the user is logged in, I want to show a new window and I want to resume the window when I want? How can I do that, I didn't know how to make it
I'll bite. Here's an example application that opens a second window when the user clicks a button on the main window, and disables interaction with the main window until the second window is closed.
Some configuration has been omitted for brevity, and I'm not using CTk here because I don't know how you've implemented it in your specific application - however, it should be easy enough to modify this example to work with CTk.
import tkinter as tk
from tkinter import ttk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.open_button = ttk.Button(
self,
text='Open 2nd Window',
command=self.modal
)
self.open_button.pack()
def modal(self):
self.window = tk.Toplevel(self) # create new window
# bind a handler for when the user closes this window
self.window.protocol('WM_DELETE_WINDOW', self.on_close)
# disable interaction with the main (root) window
self.attributes('-disabled', True)
self.close_button = ttk.Button(
self.window,
text='Close Modal',
command=self.on_close
)
self.close_button.pack()
def on_close(self):
# re-enable interaction the root window
self.attributes('-disabled', False)
# close the modal window
self.window.destroy()
if __name__ == '__main__':
app = App()
app.mailoop() # run the app
In the future:
Provide code that shows you made a good-faith effort to solve the problem on your own
Don't post the same question multiple times within hours - if you need to make changes, edit the original question
If you mean you want to open up another window to do something before going back to the original window, you should consider using message box. Here is a link that goes over the types of messageboxes: https://docs.python.org/3/library/tkinter.messagebox.html.
I want to use a dialog together with the SysTrayIcon.
The reason for the app is running in a systray, and show the dialog when you press the icon button. The app will close entirely just from the menu option.
Problem to solve: when lose focus (eg:clicking outisde) he dialog should hide even if the dialog had a button to display a modal window
Please test the sample code, as it illustrates everything.
from PySide2.QtWidgets import *
import sys
message = '''
This is a dialog we wanna use together with the SysTrayIcon
The reason of the app is running in a systray, and show the
dialog when you press the icon button. The app will close
entirely from the menu option, explained below.
Clicking SysTray icon use:
1) Click left and right in icon it shows the app
and you can interact with it. If you click again it toggles
show/hide the app.
2) With Middle Click a menu shows up, and dialog hides.
From this menu you can close the app entirely.
PROBLEM TO SOLVE:
When lose focus(eg:clicking outisde) he dialog should hide
Even if the dialog had a button to display a modal window
'''
class LauncherDialog(QDialog):
def __init__(self, x=None, y=None, parent=None):
super(LauncherDialog, self).__init__(parent)
my_lbl = QLabel(message)
my_layout = QVBoxLayout()
my_layout.addWidget(my_lbl)
my_layout.setMargin(0)
self.setLayout(my_layout)
self.setMinimumHeight(630)
self.setMinimumWidth(360)
self.setWindowTitle("Launcher")
if x is not None and y is not None:
self.move(x, y)
class SystrayLauncher(object):
def __init__(self):
# Create the icon
w = QWidget() #just to get the style(), haven't seen other way
icon = w.style().standardIcon(QStyle.SP_MessageBoxInformation)
# Create the tray
self.tray = QSystemTrayIcon()
self.tray.setIcon(icon)
self.tray.setVisible(True)
self.tray_pos = self.tray.geometry()
left = self.tray_pos.left()
height = self.tray_pos.height()
self.menu = QMenu()
self.action = QAction("&Quit", None, triggered=QApplication.instance().quit)
self.tray.setContextMenu(self.menu)
self.launcher_window = LauncherDialog(x=left, y=height)
self.tray.activated.connect(self.handleLeftRightMiddleClick)
def handleLeftRightMiddleClick(self, signal):
if signal == QSystemTrayIcon.ActivationReason.MiddleClick:
self.menu.addAction(self.action) #show menu
self.launcher_window.hide()
elif signal == QSystemTrayIcon.ActivationReason.Trigger: #left / right clicks
self.menu.removeAction(self.action) #hide menu
if self.launcher_window.isHidden():
self.launcher_window.show()
else:
self.launcher_window.hide()
else: #doubleclick
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
sl = SystrayLauncher()
sys.exit(app.exec_())
Context:
I'm creating a GUI using QtDesigner and PyCharm. The issue I am having occurs when the main window (win1) calls a second windows (win2) through a QPushButton, and then opens an error message due to lack of user input. I am using an external file (main.py) to handle the logic and events of all the windows, rather than editing code generated by QtDesigner.
Issue:
The way I have things set up, the user needs to pick an option from a comboBox, based on the user's selection, the application launches either win2 or win3
User picks no option from comboBox --> Error message
User picks option 1 --> win2 opens, win1 closes
User picks option 2 --> win3 opens, win1 closes
The problem occurs after user exits win 2/3 and goes back to win1
User picks option 1/2 --> correct window opens, no issues
User picks no option --> error message --> user closes error
message --> crash (or sudden application exit)
Note: The crash produces no errors/warnings
Here's the code I'm using to handle the opening/closing:
class win1(QtGui.QMainWindow, pg1.Ui_MainWindow):
def __init__(self, parent=None):
super(win1, self).__init__(parent)
self.setupUi(self)
self.btn1.clicked.connect(self.checkuserselection)
self.addnew = win2(self)
def checkuserselection(self):
user_str = str(self.comboBox.currentText())
if user_str == "Select Option":
self.errMsg()
elif user_str == "Option 1":
self.runaddnew("Window title for option 1")
else:
self.runaddnew("window title for option 2")
def runaddnew(self, title):
self.addnew.setWindowTitle(title)
self.addnew.show()
self.hide()
#staticmethod
def errMsg():
w = QtGui.QMessageBox()
QtGui.QMessageBox.critical(w, "No Option Selected!")
The code for win2:
class win2(QtGui.QMainWindow, pg2.Ui_MainWindow):
def __init__(self, parent=None):
super(win2, self).__init__(parent)
self.setupUi(self)
self.actionExit.triggered.connect(self.closeWindow)
def closeWindow(self):
self.close()
w = win1(self)
w.show()
The user can get the error message many times without the application suddenly quitting, as long as they haven't opened one of the other windows. This leads me to think that the issue is with the closeWindow method in win2. My knowledge in python/pyQt is limited, so I don't know if that's indeed where the issue is.
Thanks to #ekhumoro, I'm posting the response that worked here in case anyone else has this issue.
In the code for win2:
def closeWindow(self):
self.parent().show()
self.close()
This works because win1 passed self to win2 when win2 was created
I need to implement a top-level widget (fixed position on screen) that hides whenever the user clicks somewhere else in the desktop, but it should hide gradually, so the widget should still be visible when it happens. To simplify, I want something like the Windows 8 right sidebar, when the user pushes a button, like the Super key it comes up, when clicking somewhere else it fades away, but is still visible in the process.
This is, I want to have an always-on-top window that hides when it loses focus. I have implemented this in pyqt4 but it is not working.
import sys
from PyQt4 import QtGui, QtCore
class Signals(QtCore.QObject):
close = QtCore.pyqtSignal()
class Menu(QtGui.QWidget):
def __init__(self, signals):
super(Menu, self).__init__()
self.signals = signals
def mousePressEvent(self, event):
# Just simplificating the gradual hiding effect for the moment
self.signals.close.emit()
def focusOutEvent(self, event):
print "FocusOut"
self.signals.close.emit()
def main():
app = QtGui.QApplication(sys.argv)
signals = Signals()
signals.close.connect(app.quit)
w = Menu(signals)
w.setWindowFlags( QtCore.Qt.SplashScreen )
w.resize(200, 200)
w.move(0, 0)
w.setWindowTitle('Test')
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
However, this is not working. When I click somewhere else the widget won't enter the focusOutEvent. I've also tried installing an eventFilter but since the window is a SplashScreen it won't work.
Any ideas on how to tackle this?
I'm (trying to) make a small program that resides in the system tray and checks a list of Twitch channels to see if they're online every once in a while.
I'm currently doing the GUI (in PyQt4), but it's exiting for no reason.
Here's my code so far:
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class TwitchWatchTray(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
super(TwitchWatchTray, self).__init__(icon, parent)
self.menu = QtGui.QMenu(parent)
settings_action = self.menu.addAction("Settings")
settings_action.triggered.connect(self.open_settings)
self.menu.addSeparator()
exit_action = self.menu.addAction("Exit")
exit_action.triggered.connect(QtCore.QCoreApplication.instance().quit)
self.setContextMenu(self.menu)
self.show()
def open_settings(self):
settings = SettingsDialog()
settings.show()
class SettingsDialog(QtGui.QWidget):
def __init__(self):
super(SettingsDialog, self).__init__()
self.resize(300, 300)
self.setWindowTitle('TwitchWatch Settings')
vbox = QtGui.QHBoxLayout()
self.channels_list = QtGui.QListView(self)
vbox.addWidget(self.channels_list)
self.add_box = QtGui.QLineEdit(self)
vbox.addWidget(self.add_box)
self.setLayout(vbox)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
widget = QtGui.QWidget()
tw = TwitchWatchTray(QtGui.QIcon("icon.png"), widget)
app.exec_()
print("Done!")
if __name__ == '__main__':
main()
When I right click the tray icon and click "Settings", it flashes a white box (my dialog), then immediately exits and prints "Done!".
Why is this, and how do I fix it?
There are two reasons why your code exits immediately after you open the settings dialog.
The first problem is with your open_settings method:
def open_settings(self):
settings = SettingsDialog()
settings.show()
This creates a dialog and makes it visible. show() returns immediately after showing the window; it doesn't wait for the window to be closed. The settings variable goes out of scope at the end of the method, and this causes the reference count of your SettingsDialog to drop to zero and hence become eligible for garbage collection. When Python deletes the SettingsDialog object, PyQt will delete the underlying C++ object, and this is what causes the dialog to close again.
I would recommend having your settings dialog subclass QDialog rather than QWidget (it is a dialog, after all). Instead of calling settings.show() you can then call settings.exec_(). settings.exec_() does wait for the dialog to be closed before it returns. It also returns QDialog.Accepted or QDialog.Rejected depending on whether the user clicked OK or Cancel. I'd also recommend getting rid of the call to self.show() in your SettingsDialog constructor.
The second problem is that your QApplication is set to quit when the last window is closed. This is the default behaviour, which is what a lot of applications need, but not yours. Even if your dialog stayed open and you could close it, you wouldn't want your application to exit immediately after you close the settings dialog. Call app.setQuitOnLastWindowClosed(False) to fix this.