When I load a dialog (QMainWindow) window from within my mainwindow (QMainWindow), it loads without layout, even though the setupUi() function is called.
The important pieces of code are here below, click here for pastebin link to full code
class Ui_Dialog(QMainWindow):
def __init__(self, parent=None):
super(Ui_Dialog, self).__init__(parent)
self.setupUi(self)
def setupUi(self, Dialog):
...
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
self.show()
....
def setupUi(self, Form):
...
self.auto_sap_btn = QPushButton(Form)
self.auto_sap_btn.setGeometry(QRect(0, 0, 61, 25))
self.auto_sap_btn.setObjectName('auto_sap_btn')
self.auto_sap_btn.clicked.connect(self.openDialog)
def openDialog(self):
self.window = Ui_Dialog(self)
self.window.setupUi(self.window)
self.window.move(600, 500)
self.window.show()
Right now my dialog looks like this:
Failed dialog layout
When I load the dialog on its own from its own script created by:
pyuic5 -x dialog.ui -o dialog.py
it looks like this:
Proper dialog layout
What am I missing?
When you create a design based on a Template in Qt Designer, then when you have to pass the appropriate widget, when you created Ui_Dialog you surely used Dialog with Buttons Right so in this case you should use a QDialog instead of QMainWindow:
class Ui_Dialog(QDialog): # change QMainWindow to QDialog
def __init__(self, parent=None):
super(Ui_Dialog, self).__init__(parent)
self.setupUi(self)
[...]
Another mistake is to use the setupUi() method a second time since this method is responsible for filling in the widget, by calling it 2 times you will be adding more widgets unnecessarily:
def openDialog(self):
self.window = Ui_Dialog(self)
self.window.move(600, 500)
self.window.show()
Related
I am learning PyQt5 recently and have problems when I want to delete a widget in QScrollArea. Is there an elegant way to visit the element in QScrollArea and delete it when the "delete" button in that element is clicked? Thank you for any help!
class MyWidget(QWidget):
def __init__(self, id):
super().__init__()
self.layout = QHBoxLayout()
self.layout.addWidget(QPlainTextEdit(id))
self.layout.addWidget(QPushButton('Delete'))
self.setLayout(self.layout)
# connect options
connect_options()
def connect_options(self):
pass
class MyList(QScrollArea):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout()
self.widget = QWidget()
for x in range(10):
self.layout.addWidget(MyWidget(str(x)))
self.widget.setLayout(self.layout)
self.setMinimumSize(1024, 500)
self.setWidget(self.widget)
First I would suggest you look into QListWidget, It will provide you various functions to handle situations like this.
for your problem, you will need to delete the widget from its parent layout & then delete it from the GUI
class MyWidget(QWidget):
def __init__(self, id):
super().__init__()
self.layout = QHBoxLayout()
self.layout.addWidget(QPlainTextEdit(id))
del_btn = QPushButton('Delete')
del_btn.clicked.connect(self._delete) # connect the click event to your delete function
self.layout.addWidget(del_btn)
self.setLayout(self.layout)
# connect options
self.connect_options()
def connect_options(self):
pass
def _delete(self):
# here you will delete your widget
parent_layout = self.parent().layout()
parent_layout.removeWidget(self) # remove the widget from its parent layout
self.deleteLater() # lets Qt knows it needs to delete this widget from the GUI
del self
I'm using Qt Designer for design GUI to use in python, after designing my desired UI in Qt Designer, convert it to python code and then I changed generated code to do some action in my python code, but if I changed the UI with Qt Designer and convert it to python code again, I lost my previous changes on my code.
how can I solve the problem?
can we Spreading a Class Over Multiple Files in python to write code in other files?
To avoid having these problems it is advisable not to modify this file but to create a new file where we implement a class that uses that design.
For example, suppose you have used the MainWindow template in the design.ui file, then convert it to Ui_Design.py like to the following structure:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
[...]
def retranslateUi(self, MainWindow):
[...]
Then we will create a new file that we will call logic.py where we will create the file that handles the logic and that uses the previous design:
class Logic(QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
QMainWindow.__init__(self, *args, **kwargs)
self.setupUi(self)
So even if you modify the design and generate the file again .py you will not have to modify the file of the logic.
To generalize the idea we must have the following rules but for this the logic class must have the following structure:
class Logic(PyQtClass, DesignClass):
def __init__(self, *args, **kwargs):
PyQtClass.__init__(self, *args, **kwargs)
self.setupUi(self)
PyQtClass: This class depends on the design chosen.
Template PyQtClass
─────────────────────────────────────────────
Main Window QMainWindow
Widget QWidget
Dialog with Buttons Bottom QDialog
Dialog with Buttons Right QDialog
Dialog with Without Buttons QDialog
DesignClass: The name of the class that appears in your design.
The advantage of this implementation is that you can implement all the logic since it is a widget, for example we will implement the solution closing pyqt messageBox with closeevent of the parent window :
class Logic(QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
QMainWindow.__init__(self, *args, **kwargs)
self.setupUi(self)
def closeEvent(self, event):
answer = QtWidgets.QMessageBox.question(
self,
'Are you sure you want to quit ?',
'Task is in progress !',
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if answer == QtWidgets.QMessageBox.Yes:
event.accept()
else:
event.ignore()
The easiest way is to use the *.ui file directly in the python code, you don't need convert to *.py file every time you change the ui.
you can use this pseudo code in your project.
# imports
from PyQt5 import uic
# load ui file
baseUIClass, baseUIWidget = uic.loadUiType("MainGui.ui")
# use loaded ui file in the logic class
class Logic(baseUIWidget, baseUIClass):
def __init__(self, parent=None):
super(Logic, self).__init__(parent)
self.setupUi(self)
.
.
.
.
def main():
app = QtWidgets.QApplication(sys.argv)
ui = Logic(None)
ui.showMaximized()
sys.exit(app.exec_())
I am currently trying to code a pdf merger in Python and I am using tkinter to code the GUI of my application. Please note that it is my first real project in Python.
I have coded a class for my main application and I created another class named browseButton to manipulate more easily a special type of button that inherits from tkinter.Button.
However, the buttons created through this class don't appear in the main application after using grid() to place them.
Here is my code
import tkinter as tk
from tkinter import filedialog
import openFile
class mainApplication(tk.Tk):
def __init__(self, parent=None):
tk.Tk.__init__(self, parent)
self.parent=parent
self.initialize()
def initialize(self):
self.grid()
self.browseLabel=tk.Label(self, text='Select the 2 PDF files to merge.', anchor='w', fg='black')
self.browseLabel.grid(row=1, columnspan=10, pady=20)
createQuitButton(self)
createMergeButton(self)
self.browseButton1=browseButton(self)
self.browseButton2=browseButton(self)
self.browseButton1.button.grid(row=5, column=2)
self.browseButton2.button.grid(row=5, column=9)
self.browseButton1.buttonLabel.grid(row=4, column=2)
self.browseButton2.buttonLabel.grid(row=4, column=9)
def merge(self):
pass
class browseButton(tk.Button):
def __init__(self, parent=None):
tk.Button.__init__(self, parent)
self.parent=parent
self.createButton()
def openFile(self):
openFile.askOpenFile()
self.changeButtonLabel()
def createButton(self):
browseButton.buttonLabel=tk.Label(self, text='Select file', anchor='w', fg='black')
browseButton.button=tk.Button(self, text='Browse', command=self.openFile)
def changeButtonLabel(self):
self.buttonLabel['text']='File Found!
Please can someone tell me why this is not working?
I have a simple example of of a dialog window that has the keyPressEvent method. However, no matter what is typed when the sub window has focus, the event is not triggered.
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import PyQt4.Qt
class KpeWindow(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
main = QVBoxLayout(self)
label = QLabel(self)
label.setText('Test the keyPressEvent')
self.adjustSize()
self.setLayout(main)
def keyPressEvent(self, event):
QMessageBox.warning(self, 'MDI', 'keyPressEvent')
super().keyPressEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('KeyPressEvent Test')
child = KpeWindow()
self.setCentralWidget(child)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
The following code works:
class KpeWindow(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self,parent)
main = QVBoxLayout(self)
label = QLabel(self)
label.setText('Test the keyPressEvent')
main.addWidget(label)
self.adjustSize()
self.setLayout(main)
def keyPressEvent(self, event):
QMessageBox.warning(self, 'MDI', 'keyPressEvent')
self.parent().keyPressEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle('KeyPressEvent Test')
main = QVBoxLayout(self)
child = KpeWindow(self)
child.setFocusPolicy(Qt.StrongFocus)
self.setFocusProxy(child)
main.addWidget(child)
child.setFocus(True)
self.adjustSize()
self.setLayout(main)
I am not sure which of my changes work, I suspect setFocusProxy. In general I would recommend using QWidget as the child, and putting things into layouts even when there are no siblings.
The keyPressEvent is sensitive to the focus policy. In your example, the event is going to the QMainWindow (if you move the keyPressEvent to there, it does receive key events).
Is there any reason to have a dialog within a window? If you launch the dialog in the usual way, using child.show(), child.exec_() instead of setCentralWidget, it shows in a separate window and captures the key event.
I have a mainwindow containing many dockwidget, toolbars,and menubars. I am able to toggle the visibility of dockwidgets and toolbars but not the menubars. Why does not the below code work?
Is it possible to view only the central widget of a QMainWindow as full screen in PyQt by hiding the menubars?
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.local_grview = QGraphicsView()
self.local_grview.setSceneRect(0,0,200,200)
self.setCentralWidget(self.local_grview)
def fullscreen(self):
self.hide()
self.setParent(None)
self.local_grview.showFullScreen()
self.local_grview.show()