I want to add startup window that when I click button, it will open another window and close current window. For each window, it has seperated UI which created from Qt Designer in .ui form.
I load both .ui file via uic.loadUiType(). The first window(first UI) can normally show its UI but when I click button to go to another window, another UI (second UI) doesn't work. It likes open blank window.
Another problem is if I load first UI and then change to second UI (delete that Class and change to another Class, also delete uic.loadUiType()), the second UI still doesn't work (show blank window)
Please help... I research before create this question but can't find the answer.
Here's my code. How can I fix it?
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
from PyQt5 import uic
#load both ui file
uifile_1 = 'UI/openPage.ui'
form_1, base_1 = uic.loadUiType(uifile_1)
uifile_2 = 'UI/mainPage.ui'
form_2, base_2 = uic.loadUiType(uifile_2)
class Example(base_1, form_1):
def __init__(self):
super(base_1,self).__init__()
self.setupUi(self)
self.startButton.clicked.connect(self.change)
def change(self):
self.main = MainPage()
self.main.show()
class MainPage(base_2, form_2):
def __int__(self):
super(base_2, self).__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
First you have an error, you must change __int__ to __init__. To close the window call the close() method.
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
from PyQt5 import uic
#load both ui file
uifile_1 = 'UI/openPage.ui'
form_1, base_1 = uic.loadUiType(uifile_1)
uifile_2 = 'UI/mainPage.ui'
form_2, base_2 = uic.loadUiType(uifile_2)
class Example(base_1, form_1):
def __init__(self):
super(base_1,self).__init__()
self.setupUi(self)
self.startButton.clicked.connect(self.change)
def change(self):
self.main = MainPage()
self.main.show()
self.close()
class MainPage(base_2, form_2):
def __init__(self):
super(base_2, self).__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
Related
I'm trying to open a file in my PySide2 application, but the file dialog always opens below the main window and appears as another application in the launcher. The application's name is "Portal".
I see other answers where the solution is to pass the main window as the first parameter to getOpenFileName(), but that doesn't work for me.
Here's a simple demonstration of the problem:
import sys
from PySide2.QtWidgets import QPushButton, QFileDialog, QApplication
class DemoButton(QPushButton):
def __init__(self, text):
super().__init__(text)
self.clicked.connect(self.on_click)
def on_click(self):
file_name, _ = QFileDialog.getOpenFileName(
self,
"Open a text file.",
filter='Text file (*.txt)')
print(file_name)
def main():
app = QApplication(sys.argv)
button = DemoButton("Hello World")
button.show()
app.exec_()
sys.exit()
main()
I thought maybe the parent had to be a QMainWindow, so I tried that:
import sys
from PySide2 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
main_widget = QtWidgets.QWidget(self)
self.setCentralWidget(main_widget)
# layout initialize
g_layout = QtWidgets.QVBoxLayout()
layout = QtWidgets.QFormLayout()
main_widget.setLayout(g_layout)
# Add Widgets
self.exec_btn = QtWidgets.QPushButton('Execute')
self.exec_btn.clicked.connect(self.find_file)
# global layout setting
g_layout.addLayout(layout)
g_layout.addWidget(self.exec_btn)
def find_file(self):
file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
"Open a text file.",
filter='Text file (*.txt)')
print(file_name)
def main():
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
sys.exit()
main()
The file dialog behaved exactly the same.
I'm using PySide2 5.12.2, Python 3.6.7, and running on Ubuntu 18.04.
Thanks to ekhumoro's comment, I learned that I can tell PySide2 not to use the native file dialog.
import sys
from PySide2.QtWidgets import QPushButton, QFileDialog, QApplication
class DemoButton(QPushButton):
def __init__(self, text):
super().__init__(text)
self.clicked.connect(self.on_click)
def on_click(self):
file_name, _ = QFileDialog.getOpenFileName(
self,
"Open a text file.",
filter='Text file (*.txt)',
options=QFileDialog.DontUseNativeDialog)
print(file_name)
def main():
app = QApplication(sys.argv)
button = DemoButton("Hello World")
button.show()
app.exec_()
sys.exit()
main()
That fixes the behaviour by bringing the file dialog to the front, but I think the native file dialog looks better. Hopefully, there's another option that can make the native file dialog work properly.
I have two windows (App.py and ChildApp.py) and .ui files for both with same name.
App.py:
import sys
from PyQt4 import QtCore, QtGui, uic
from ChildApp import ChildApp
qtCreatorFile = "App.ui" # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class App(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.message = None
self.child_window = ChildApp()
self.pushButton.clicked.connect(self.sendMessage)
def sendMessage(self):
self.message = self.lineEdit.text()
self.child_window.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = App()
window.show()
sys.exit(app.exec_())
ChildApp.py:
import sys
from PyQt4 import QtCore, QtGui, uic
qtCreatorFile = "ChildApp.ui" # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class ChildApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.pushButton.clicked.connect(self.alertmessage)
def alertmessage(self):
message = "test"
self.label.setText("Message : "+message)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = ChildApp()
window.show()
sys.exit(app.exec_())
In Main.py file I have a variable self.message.
When I click on the button "Do something with text", text in the textbox is assigned to self.message and the child window is opened.
Now in the child window, when I click on button "Show message", the method alertmessage() is called, where it sets message = "text".
This variable message must be assigned to value of self.message from MainApp.py.
Please help
Thank you
Call the child that way:
self.child_window = ChildApp(parent=self)
Define the child app this way:
class ChildApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent):
self.parent = parent
you can use the parent variables through self.parent.whatever
It must work, but I wouldn't advise this because you are not supposed to know the fields of the parent form the child.
I don't think you can get local data from the parent. I would do the following:
Use a signal to update the child when the text is changed in the lineEdit:
self.lineEdit.textChanged.connect(self.updateChild)
Add this function in the main window:
def updateChild(self):
self.child_window.setMessage(self.lineEdit.text())
and keep the variable self._message updated in the child window:
def setMessage(self, message):
self._message=message
so that whenever you need this variable, it is up to date
I am trying to translate my small application written in pyside2/pyqt5 to several languages, for example, Chinese. After googling, I managed to change the main window to Chinese after select from the menu -> language -> Chinese. However, the pop up dialog from menu -> option still remains English version. It seems the translation info is not transferred to the dialog. How do I solve this?
Basically, I build two ui files in designer and convert to two python files:One mainui.py and one dialogui.py. I then convert the two python file into one *.ts file using
pylupdate5 -verbose mainui.py dialogui.py -ts zh_CN.ts
after that, in linguist input the translation words. I can see the items in the dialog, which means this information is not missing. Then I release the file as zh_CN.qm file. All this supporting file I attached below using google drive.
Supporting files for the question
The main file is as
import os
import sys
from PySide2 import QtCore, QtGui, QtWidgets
from mainui import Ui_MainWindow
from dialogui import Ui_Dialog
class OptionsDialog(QtWidgets.QDialog,Ui_Dialog):
def __init__(self,parent):
super().__init__(parent)
self.setupUi(self)
self.retranslateUi(self)
class MainWindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.actionConfigure.triggered.connect(self.showdialog)
self.actionChinese.triggered.connect(self.change_lang)
def showdialog(self):
dlg = OptionsDialog(self)
dlg.exec_()
def change_lang(self):
trans = QtCore.QTranslator()
trans.load('zh_CN')
QtCore.QCoreApplication.instance().installTranslator(trans)
self.retranslateUi(self)
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
ret = app.exec_()
sys.exit(ret)
I think it should be a typical task because almost no application will only have a mainwindow.
You have to overwrite the changeEvent() method and call retranslateUi() when the event is of type QEvent::LanguageChange, on the other hand the QTranslator object must be a member of the class but it will be deleted and it will not exist when the changeEvent() method is called.
Finally assuming that the Language menu is used to establish only translations, a possible option is to establish the name of the .qm as data of the QActions and to use the triggered method of the QMenu as I show below:
from PySide2 import QtCore, QtGui, QtWidgets
from mainui import Ui_MainWindow
from dialogui import Ui_Dialog
class OptionsDialog(QtWidgets.QDialog,Ui_Dialog):
def __init__(self,parent):
super().__init__(parent)
self.setupUi(self)
def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange:
self.retranslateUi(self)
super(OptionsDialog, self).changeEvent(event)
class MainWindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.m_translator = QtCore.QTranslator(self)
self.actionConfigure.triggered.connect(self.showdialog)
self.menuLanguage.triggered.connect(self.change_lang)
# set translation for each submenu
self.actionChinese.setData('zh_CN')
#QtCore.Slot()
def showdialog(self):
dlg = OptionsDialog(self)
dlg.exec_()
#QtCore.Slot(QtWidgets.QAction)
def change_lang(self, action):
QtCore.QCoreApplication.instance().removeTranslator(self.m_translator)
if self.m_translator.load(action.data()):
QtCore.QCoreApplication.instance().installTranslator(self.m_translator)
def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange:
self.retranslateUi(self)
super(MainWindow, self).changeEvent(event)
if __name__=='__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
ret = app.exec_()
sys.exit(ret)
I am trying to write a PyQt5 application that does the following:
Creates and opens a Main Window. The MainWindow has a function that opens a QFileDialog window.
Function to open QFileDialog can be triggered in two ways (1) from a file menu option called 'Open' (2) automatically, after the Main window is shown.
My problem is that I haven't found a way to get the QfileDialog to automatically open (2) that doesn't cause the application to hang when the main window is closed. Basic example of code can be found below:
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QWidget,
QHBoxLayout, QCalendarWidget, QScrollArea, QFileDialog, QAction, QFrame)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.openAction = QAction(QIcon('/usr/share/icons/breeze/places/64/folder-open.svg'), 'Open', self)
self.openAction.triggered.connect(self.openDialog)
self.menubar = QMenuBar(self)
fileMenu = self.menubar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.event_widgets = EventWidgets(self)
self.setMenuBar(self.menubar)
self.setCentralWidget(self.event_widgets)
def openDialog(self):
ics_path = QFileDialog.getOpenFileName(self, 'Open file', '/home/michael/')
class EventWidgets(QWidget):
def __init__(self, parent):
super(EventWidgets, self).__init__(parent)
self.initUI()
def initUI(self):
self.calendar = QCalendarWidget(self)
self.frame = QFrame()
self.scrollArea = QScrollArea()
self.scrollArea.setWidget(self.frame)
horizontal_box = QHBoxLayout()
horizontal_box.addWidget(self.calendar)
horizontal_box.addWidget(self.scrollArea)
self.setLayout(horizontal_box)
if __name__ == '__main__':
app = QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
app_window.openDialog()
sys.exit(app.exec_())
Code has been tested on KDE Neon and Arch Linux, both have same issue.
I can get round this issue by handling the close event of the Main Window manually - i.e. adding this function to MainWindow:
def closeEvent(self, event):
sys.exit()
But I am not sure a) why this is necessary b) if it is best practice.
I tried your code on macOS Sierra and it works as it's supposed to. However I would propose a different approach to solve your problem.
What you could do is to implement the showEvent() function in your MainWindow class, which is executed whenever a widget is displayed (either using .show() or .showMaximized()) and trigger your custom slot to open the QFileDialog. When doing this you could make use of a single shot timer to trigger the slot with some minimal delay: the reason behind this is that if you simply open the dialog from within the showEvent(), you will see the dialog window but not the MainWindow below it (because the QFileDialog is blocking the UI until the user perform some action). The single shot timer adds some delay to the opening of the QFileDialog, and allows the MainWindow to be rendered behind the modal dialog. Here is a possible solution (not that I made some minor changes to your code, which you should be able to easily pick up):
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.openAction = QtWidgets.QAction('Open', self)
self.openAction.triggered.connect(self.openDialog)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.event_widgets = EventWidgets(self)
self.setCentralWidget(self.event_widgets)
def showEvent(self, showEvent):
QtCore.QTimer.singleShot(50, self.openDialog)
#QtCore.pyqtSlot()
def openDialog(self):
ics_path = QtWidgets.QFileDialog.getOpenFileName(self, 'Open file', '/Users/daniele/')
class EventWidgets(QtWidgets.QWidget):
def __init__(self, parent):
super(EventWidgets, self).__init__(parent)
self.calendar = QtWidgets.QCalendarWidget(self)
self.frame = QtWidgets.QFrame()
self.scrollArea = QtWidgets.QScrollArea()
self.scrollArea.setWidget(self.frame)
horizontal_box = QtWidgets.QHBoxLayout()
horizontal_box.addWidget(self.calendar)
horizontal_box.addWidget(self.scrollArea)
self.setLayout(horizontal_box)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
sys.exit(app.exec_())
Hi I have designed a basic GUI in QT and created a .py file from it.
When the window starts up I want to add another menu item. I have tried a few pieces of code I found on google but nothing seems to work. The code will need to go in the method addAdminMenu()
from PyQt4 import QtGui
import sys
from supplypy.core.windows.main_window import Ui_MainWindow
class SRM(QtGui.QWidget):
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.MainWindow = QtGui.QMainWindow()
self.ui = Ui_MainWindow()
self.ui.setupUi(self.MainWindow)
self.MainWindow.show()
sys.exit(self.app.exec_())
def addAdminMenu(self):
pass
#####Add code here to create a Admin menu####
if __name__ == '__main__':
srm = SRM()
It should be as simple as accessing the menuBar() of the QMainWindow and adding an item, for example: (I removed the Ui_MainWindow lines just because I don't know what it's for -- a Windows requirement?)
from PyQt4 import QtGui
import sys
class SRM(QtGui.QWidget):
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.MainWindow = QtGui.QMainWindow()
self.menubar = self.MainWindow.menuBar()
self.MainWindow.show()
self.addAdminMenu()
sys.exit(self.app.exec_())
def addAdminMenu(self):
self.menubar.addMenu('&Admin');
if __name__ == '__main__':
srm = SRM()