PyQT: Exit/Complete Second Window Before First Window - python

I have the following code below:
from PyQt4 import QtGui
import sys
class Second(QtGui.QWidget):
def __init__(self, parent=None):
super(Second, self).__init__(parent)
self.grid = QtGui.QGridLayout(self)
self.setGeometry(650,400,400,200)
self.widget = QtGui.QWidget()
class First(QtGui.QMainWindow):
def __init__(self, parent=None):
super(First, self).__init__(parent)
self.grid = QtGui.QGridLayout(self)
self.setGeometry(350, 200, 1000, 700)
self.widget = QtGui.QWidget()
Button1 = QtGui.QPushButton('...', self)
Button1.clicked.connect(self.on_pushButton_clicked)
self.grid.addWidget(Button1, 0, 0, 1, 1)
def on_pushButton_clicked(self):
self.Second = Second()
self.Second.setWindowTitle('Window')
self.Second.show()
def main():
app = QtGui.QApplication(sys.argv)
main = First()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
When I click the button, I want to be able to finish up my action in the second window before continuing on the first. Right now, I can exit out of my first window and the second window remains open. How do you keep on the second window but keep the first window unselectable?

There are 2 possible solutions:
- Second must inherit from QDialog, pass it as parent to the first window and use exec_() instead of show:
class Second(QtGui.QDialog):
def __init__(self, parent=None):
super(Second, self).__init__(parent)
class First(QtGui.QMainWindow):
def __init__(self, parent=None):
super(First, self).__init__(parent)
self.setGeometry(350, 200, 1000, 700)
self.widget = QtGui.QWidget()
self.setCentralWidget(self.widget)
grid = QtGui.QGridLayout(self.widget)
Button1 = QtGui.QPushButton('...', self)
Button1.clicked.connect(self.on_pushButton_clicked)
grid.addWidget(Button1, 0, 0, 1, 1)
#QtCore.pyqtSlot()
def on_pushButton_clicked(self):
self.Second = Second(self)
self.Second.setWindowTitle('Window')
self.Second.exec_()
- Change the windowModality to Qt::WindowModal, activate the flag Qt::Dialog and pass it the first window as parent.
class Second(QtGui.QWidget):
def __init__(self, parent=None):
super(Second, self).__init__(parent)
self.setWindowModality(QtCore.Qt.WindowModal)
self.setWindowFlags(self.windowFlags() | QtCore.Qt.Dialog)
class First(QtGui.QMainWindow):
def __init__(self, parent=None):
super(First, self).__init__(parent)
self.setGeometry(350, 200, 1000, 700)
self.widget = QtGui.QWidget()
self.setCentralWidget(self.widget)
grid = QtGui.QGridLayout(self.widget)
Button1 = QtGui.QPushButton('...', self)
Button1.clicked.connect(self.on_pushButton_clicked)
grid.addWidget(Button1, 0, 0, 1, 1)
#QtCore.pyqtSlot()
def on_pushButton_clicked(self):
self.Second = Second(self)
self.Second.setWindowTitle('Window')
self.Second.show()

Related

PyQt5 Automatic drawing from input value

I have recently created a widget with Qpaint, which I want to pass value to it, at the same time force the Qpaint Widget to draw from input values. The idea is to define a data value from a Qdialog and pass it to main widget, and pass the value to Qpaint Widget class. I would like to have, when user clicks on the button 'Getting values' a dialog widget would appear and insert some int values, then pass it to main Widget. from there pass value to correct class Paint. Which would draw and display the result. I tried with Qlabel, to assign value first to Qlabel or QlineEdit,
class Button(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Button, self).__init__(parent)
---------
self.value = QtWidgets.QLabel()
--------
Then inside the paint class call the value or text of those. then assign it to Qpaint event. But seems does not work.'
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.button = Button()
self.Value = self.button.value
---------
painter.drawRect(100,100,250,250) <----- instead of value 250 having self.Value
The code Main.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from datainput import *
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 800, 800))
self.button = Button()
self.paint = Paint()
self.lay = QtWidgets.QVBoxLayout()
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
self.setLayout(self.lay)
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.button = Button()
self.Value = self.button.value
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
def paintEvent(self, event):
self.pen = QtGui.QPen()
self.brush = QtGui.QBrush( QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(self.pen)
painter.setBrush(self.brush)
painter.drawRect(100,100,250,250)
painter.setBrush(QtGui.QBrush())
class Button(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Button, self).__init__(parent)
getbutton = QtWidgets.QPushButton('Getting values')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(getbutton)
self.value = QtWidgets.QLabel()
getbutton.clicked.connect(self.getbuttonfunc)
def getbuttonfunc(self):
subwindow=Dinput()
subwindow.setWindowModality(QtCore.Qt.ApplicationModal)
if subwindow.exec_() == QtWidgets.QDialog.Accepted:
self._output = subwindow.valueEdit.text()
return self.value.setText(self._output)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
Input Qdialog code, datainput.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Dinput(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Dinput, self).__init__(parent)
valuelabel = QtWidgets.QLabel('Input: ')
self.valueEdit = QtWidgets.QLineEdit()
buttonBox = QtWidgets.QDialogButtonBox()
buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.close)
self.Alay = QtWidgets.QHBoxLayout()
self.Alay.addWidget(valuelabel)
self.Alay.addWidget(self.valueEdit)
self.Blay = QtWidgets.QVBoxLayout()
self.Blay.addLayout(self.Alay)
self.Blay.addWidget(buttonBox)
self.setLayout(self.Blay)
def closeEvent(self, event):
super(Dinput, self).closeEvent(event)
def accept(self):
super(Dinput, self).accept()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Dinput()
w.show()
sys.exit(app.exec_())
Visualization
I appreciate any help. Thankssss
datainput is irrelevant, your task is only to obtain a number so for space question I will not use it and instead I will use QInputDialog::getInt(). Going to the problem, the strategy in these cases where the value can be obtained at any time is to notify the change to the other view through a signal, in the slot that receives the value is to update a variable that stores the value and call update so that it calls when necessary to paintEvent, and in the paintEvent use the variable that stores the value.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 800, 800))
self.button = Button()
self.paint = Paint()
self.button.valueChanged.connect(self.paint.set_size_square)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size_square = 250
#QtCore.pyqtSlot(int)
def set_size_square(self, v):
self._size_square = v
self.update()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush( QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
r = QtCore.QRect(QtCore.QPoint(100, 100), self._size_square*QtCore.QSize(1, 1))
painter.drawRect(r)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
getbutton = QtWidgets.QPushButton('Getting values')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(getbutton)
self.value = QtWidgets.QLabel()
getbutton.clicked.connect(self.getbuttonfunc)
#QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())

When one checkbox is checked, by pressing a button to print some texts from a LineEdit if another checkbox is also checked

import sys, os
import PyQt4
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Tab1Widget1(QWidget):
def __init__(self, parent=None):
super().__init__()
self.Tab1Widget1initUI()
self.bridge = Tab1Widget2()
def Tab1Widget1initUI(self):
self.setLayout(QGridLayout())
self.T1W1_checkbox = QCheckBox('checkbox1', self)
self.layout().addWidget(self.T1W1_checkbox, 1, 0)
def test(self):
print ('123')
def run(self):
if self.T1W1_checkbox.isChecked() == True:
self.test()
if self.bridge.T1W2_checkbox.isChecked() == True:
print (self.bridge.T1W2_le.text())
class Tab1Widget2(QWidget):
def __init__(self, parent=None):
super().__init__()
self.setLayout(QGridLayout())
self.T1W2_checkbox = QCheckBox('checkbox2', self)
self.layout().addWidget(self.T1W2_checkbox, 0, 0)
self.T1W2_le = QLineEdit()
self.layout().addWidget(self.T1W2_le, 0, 1)
class Tab1Layout(QWidget):
def __init__(self, parent=None):
super().__init__()
self.setLayout(QGridLayout())
self.group1 = Tab1Widget1(self)
scroll = QScrollArea(self)
scroll.setWidget(self.group1)
scroll.setWidgetResizable(True)
self.layout().addWidget(scroll, 0, 0)
self.group2 = Tab1Widget2(self)
self.layout().addWidget(self.group2, 1, 0)
self.btnRun = QPushButton('Run', self)
self.layout().addWidget(self.btnRun, 3, 0)
self.btnRun.clicked.connect(self.group1.run)
class Page1(QTabWidget):
def __init__(self, parent=None):
super().__init__()
self.tab1 = Tab1Layout()
self.addTab(self.tab1, "Tab1")
self.tab2 = QWidget()
self.tab3 = QWidget()
self.addTab(self.tab2, "Tab2")
self.addTab(self.tab3, "Tab3")
self.tab2_initUI()
self.tab3_initUI()
def tab2_initUI(self):
grid = QGridLayout()
self.tab2.setLayout(grid)
def tab3_initUI(self):
grid = QGridLayout()
self.tab3.setLayout(grid)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__()
self.setGeometry(450, 250, 800, 550)
self.startPage1()
def startPage1(self):
x = Page1(self)
self.setWindowTitle("Auto Benchmark")
self.setCentralWidget(x)
self.show()
def main():
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
If checkbox1 is checked and I press the run button, it will print 123. However, by pressing run button, I want checkbox2 to also print some texts entered in lineedit if the checkbox1 are also checked (i.e. it should print 123 first and then print 456).
I've looked up some similar types of questions, but none of that provides a proper answer. If anyone knows how to solve it, pls let me know thanks!!
The problem is that you are creating several Tab1Widget2, the first one you created in Tab1Layout, and that is the one you see, then you have created another one in Tab1Widget1, but not the time because you have not passed a parent, if you pass it to ** self ** as parent you will observe the following:
self.bridge = Tab1Widget2(self)
which is not what you want, so instead of creating a new you must pass the one that already exists, an option is to pass it through the constructor:
class Tab1Widget1(QWidget):
def __init__(self, bridge, parent=None): # Modify here
super().__init__(parent)
self.Tab1Widget1initUI()
self.bridge = bridge #Modify here
# ...
def test(self): print ('123')
def run(self):
if self.T1W1_checkbox.isChecked():
self.test()
if self.bridge.T1W2_checkbox.isChecked():
print (self.bridge.T1W2_le.text())
class Tab1Widget2(QWidget):
# ...
class Tab1Layout(QWidget):
def __init__(self, parent=None):
super().__init__()
self.setLayout(QGridLayout())
self.group2 = Tab1Widget2(self) # Modify here
self.group1 = Tab1Widget1(self.group2, self) # Modify here
scroll = QScrollArea(self)
scroll.setWidget(self.group1)
scroll.setWidgetResizable(True)
self.layout().addWidget(scroll, 0, 0)
# self.group2 = Tab1Widget2(self) # Modify here
self.layout().addWidget(self.group2, 1, 0)
# ...

Wrong layout in QMainWindow?

I am getting wrong layout in PyQT5. What am I doing wrong? Is there some predefined small field size or similar? I created main window as QMainWindow and inside it a widget as central widget. This is how it looks like:
class Main(QWidget):
"""The main widget with label and LineEdit"""
def __init__(self, parent=None):
super().__init__(parent)
self.initUi()
def initUi(self):
"""Initialize the UI of the main widget"""
self.mySourceLabel = QLabel("Select your file:")
self.mySourceLine = QLineEdit()
self.mySourceLine.setPlaceholderText("File name here")
# Set layout
grid = QGridLayout()
#grid.setSpacing(5)
grid.addWidget(self.mySourceLabel, 0, 0)
grid.addWidget(self.mySourceLine, 1, 0)
self.setLayout(grid)
class MyApp(QMainWindow):
"""Main application class"""
def __init__(self, parent=None):
super().__init__(parent)
self.initUi()
def initUi(self):
"""Initialize UI of an application"""
# main window size, title
self.setGeometry(400, 300, 400, 300)
self.setWindowTitle("Version upgrade ")
# create instance of a class Main
self.main = Main(self)
# create central widget, create grid layout
centralWidget = QWidget()
centralLayout = QGridLayout()
centralWidget.setLayout(centralLayout)
When you pass the parent to a QWidget this will locate a position with respect to its parent and generate widgets like the ones you have obtained, to solve this, layouts are used, QMainWindow is a special QWidget since it has predefined elements, so it already has a layout:
In QMainWindow the widget must be added to the centralwidget with the setCentralWidget function, in your case:
class MyApp(QMainWindow):
"""Main application class"""
def __init__(self, parent=None):
super().__init__(parent)
self.initUi()
def initUi(self):
[...]
centralWidget = Main(self)
self.setCentralWidget(centralWidget)
complete code:
class Main(QWidget):
"""The main widget with label and LineEdit"""
def __init__(self, parent=None):
super().__init__(parent)
self.initUi()
def initUi(self):
"""Initialize the UI of the main widget"""
self.mySourceLabel = QLabel("Select your file:")
self.mySourceLine = QLineEdit()
self.mySourceLine.setPlaceholderText("File name here")
# Set layout
grid = QGridLayout()
#grid.setSpacing(5)
grid.addWidget(self.mySourceLabel, 0, 0)
grid.addWidget(self.mySourceLine, 1, 0)
self.setLayout(grid)
class MyApp(QMainWindow):
"""Main application class"""
def __init__(self, parent=None):
super().__init__(parent)
self.initUi()
def initUi(self):
"""Initialize UI of an application"""
# main window size, title
self.setGeometry(400, 300, 400, 300)
self.setWindowTitle("Version upgrade ")
# create central widget, create grid layout
centralWidget = Main(self)
self.setCentralWidget(centralWidget)
Screenshot:

How can I pass data in run method (thread) (python, Pyqt)

I want to make the thread, in the window, using PyQt(Python). For example
class window(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(100, 100, 500, 200)
self.setWindowTitle('Hello')
self.label = QtGui.QLabel(u'WoRLd', self)
self.Layout = QtGui.QVBoxLayout()
self.Layout.addWidget(self.label)
self.setLayout(self.Layout)
self.introduced = 123
self.request = Requests()
self.request.start()
self.connect(self.request, QtCore.SIGNAL("mysignal(QString)"),
self.on_change, QtCore.Qt.QueuedConnection)
def on_change(self, s):
self.label.setText(s)
class Requests():
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
def run(self):
self.emit(QtCore.SIGNAL("mysignal(QString)"), "143242" )
app = QtGui.QApplication(sys.argv)
main = window()
main.show()
sys.exit(app.exec_())
But, in method "run", I need some dates from "class window" (variable: introduced).
How can I pass this variable to "def run"?
you just have to make arguments for it and pass it into the class instance. then assign it to self.date, this makes it accesible across the class instance:
class window(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(100, 100, 500, 200)
self.setWindowTitle('Hello')
self.label = QtGui.QLabel(u'WoRLd', self)
self.Layout = QtGui.QVBoxLayout()
self.Layout.addWidget(self.label)
self.setLayout(self.Layout)
self.introduced = 123
date = # get some date whatever you need to pass here
self.request = Requests(date)
self.request.start()
self.connect(self.request, QtCore.SIGNAL("mysignal(QString)"),
self.on_change, QtCore.Qt.QueuedConnection)
def on_change(self, s):
self.label.setText(s)
class Requests():
def __init__(self, date, parent=None):
self.date = date
QtCore.QThread.__init__(self, parent)
def run(self):
# do something with self.date here
self.emit(QtCore.SIGNAL("mysignal(QString)"), "143242" )
app = QtGui.QApplication(sys.argv)
main = window()
main.show()
sys.exit(app.exec_())

Qt and python - how to refer to another class

I have main window which contains scene and button in widget from where I need to call scene:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class Widget(QWidget):
def __init__(self, scene):
super(Widget, self).__init__()
self.refreshButton = QPushButton("Refresh", self)
self.refreshButton.clicked.connect(self.Refresh)
# THIS ACTION SHOULD PROCEED ARGUMENTS
# TO FUNCION "Refresh"
layout = QHBoxLayout()
layout.addWidget(self.refreshButton)
self.setLayout(layout)
self.show()
def Refresh(self, scene):
mainWinScene = scene
print "On Refresh! - ", mainWinScene.items()
class MainScene(QGraphicsScene):
def __init__(self):
super(MainScene, self).__init__()
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.scene = MainScene()
self.scene.setSceneRect(0,0,200,100)
self.scene.addLine(20,10,150,80)
self.view = QGraphicsView()
self.view.setScene(self.scene)
drawRectAct = QAction('&Add Rectangle', self)
drawRectAct.triggered.connect(self.drawRect)
shapeInspectorAct = QAction('&Show Inspector', self)
shapeInspectorAct.triggered.connect(self.showInspector)
menubar = self.menuBar()
fileMenu = menubar.addMenu('&Shapes')
fileMenu.addAction(drawRectAct)
fileMenu.addAction(shapeInspectorAct)
self.setCentralWidget(self.view)
def drawRect(self):
self.scene.addRect(50,50,20,30)
def showInspector(self):
self.I = Widget(self.scene)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
How to proceed "scene" argument with action - to "Refresh" function?
You can pass a scene in Widget's constructor:
class Widget(QWidget):
def __init__(self, scene):
...
self.scene = scene
...
def Refresh(self):
print "On Refresh! - ", self.scene.items()
class MainWindow(QMainWindow):
...
def showInspector(self):
self.I = Widget(self.scene)
...

Categories