PyQt - Program to close window with model and view - python

Can anyone help me make a good code write and help me to understand the SIGNAL and SLOT with Model and View.
With easy examples and codes i am new in Python and Qt5 and i try to learn in easy way.
I have books with me to learn faster but books do it more complicated to learn and don't do it step by step.
Thank you.
import sys
from PyQt5 import QtWidgets as qtW
from PyQt5 import QtCore as qtC
class Model(qtW.QWidget, qtC.QObject):
quit = qtC.pyqtSignal(bool)
message_quit = "GOODBYE !"
def exit_window(self):
print(self.message_quit)
self.quit.emit(self.close())
class View(qtW.QWidget):
message = "Tape Text Here !"
message_show = "Your message shown here !"
button_show = "SHOW"
button_quit = "QUIT"
message_quit = "GOODBYE !"
def __init__(self):
super().__init__()
self.grid = qtW.QGridLayout()
self.setLayout(self.grid)
self.message_lineEdit = qtW.QLineEdit(self.message)
self.grid.addWidget(self.message_lineEdit, 0, 0)
self.message_label = qtW.QLabel(self.message_show)
self.grid.addWidget(self.message_label, 1, 0)
self.quit_button = qtW.QPushButton(self.button_quit)
self.grid.addWidget(self.quit_button, 2, 0)
class MainWindow(qtW.QMainWindow):
def __init__(self):
super().__init__()
self.view = View()
self.setCentralWidget(self.view)
self.model = Model()
self.view.quit_button.clicked.connect(self.model.exit_window)
self.show()
if __name__ == '__main__':
app = qtW.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())

The signal / pyqtSignal() must be created at the origin, in this case in View() and not in Model(). Just like the issue / emit(), it must also be put at the origin.
import sys
from PyQt5 import QtWidgets as qtW
from PyQt5 import QtCore as qtC
class Model(qtW.QWidget, qtC.QObject):
#quit = qtC.pyqtSignal(bool)
message_quit = "GOODBYE !"
def exit_window(self, bool):
print(self.message_quit)
#self.quit.emit(self.close())
class View(qtW.QWidget):
signEmit1 = qtC.pyqtSignal(bool)
message = "Tape Text Here !"
message_show = "Your message shown here !"
button_show = "SHOW"
button_quit = "QUIT"
message_quit = "GOODBYE !"
def __init__(self):
super().__init__()
self.grid = qtW.QGridLayout()
self.setLayout(self.grid)
self.message_lineEdit = qtW.QLineEdit(self.message)
self.grid.addWidget(self.message_lineEdit, 0, 0)
self.message_label = qtW.QLabel(self.message_show)
self.grid.addWidget(self.message_label, 1, 0)
self.quit_button = qtW.QPushButton(self.button_quit)
self.grid.addWidget(self.quit_button, 2, 0)
self.quit_button.clicked.connect(self.btnAction)
def btnAction(self):
self.signEmit1.emit(True)
class MainWindow(qtW.QMainWindow):
def __init__(self):
super().__init__()
self.model = Model()
self.view = View()
self.view.signEmit1.connect(self.model.exit_window)
self.setCentralWidget(self.view)
self.show()
if __name__ == '__main__':
app = qtW.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
Hope this helps

Related

Using qHelpEngine

I want to make a help file using QtHelp and QHelpEngine. I currently have some code but I am not sure about my errors and the documentation is a little vague in my opinion. Nonetheless the current issue I am facing is one of connecting signal and slots. The error I currently get is AttributeError: 'builtin_function_or_method' object has no attribute 'linkActivated' Not sure the reason for this as the documentation states that contentWidget does have a signal called linkActivated. And an error occurs here textViewer = QtWidgets.QTextBrowser(helpEngine)
Reference
from PyQt5 import QtCore, QtGui, QtWidgets, QtHelp
import os
class Ui_HelpSetupClass(QtWidgets.QDockWidget):
def __init__(self):
super().__init__()
self.setupUi(self)
def setupUi(self, HelpSetupClass):
qUrl = "qthelp://ut.tool.help/tool/index.html"
HELP_DIR = os.getcwd()
HELP_PATH = HELP_DIR + "\\" + "Help" + "\\" + "help_file.qhc"
helpEngine = QtHelp.QHelpEngine(HELP_PATH)
helpEngine.setupData()
tableWidget = QtWidgets.QTabWidget()
tableWidget.setMaximumWidth(200)
tableWidget.addTab(helpEngine.contentWidget(), "Contents")
tableWidget.addTab(helpEngine.indexWidget(), "Index")
textViewer = QtWidgets.QTextBrowser(helpEngine)
textViewer.setSource(qUrl)
helpEngine.contentWidget.linkActivated(qUrl ).connect(textViewer.setSource(qUrl))
helpEngine.indexWidget.documentActivated(qUrl ).connect(textViewer.setSource(qUrl))
horizSplitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
horizSplitter.insertWidget(0, tableWidget)
horizSplitter.insertWidget(1, textViewer)
horizSplitter.hide()
helpWindow = QtWidgets.QDockWidget("Help", self)
helpWindow.setWidget(horizSplitter)
helpWindow.hide()
QtWidgets.QMainWindow.addDockWidget(QtCore.Qt.BottomDockWidgetArea, helpWindow)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ui = Ui_HelpSetupClass()
ui.show()
sys.exit(app.exec_())
In your translation of the C++ code to Python it shows many errors so I will avoid pointing it out and I will only show the correct translation:
import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtHelp
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
class HelpBrowser(QtWidgets.QTextBrowser):
def __init__(self, helpEngine, parent=None):
super().__init__(parent)
self.helpEngine = helpEngine
def loadResource(self, _type, name):
if name.scheme() == "qthelp":
return self.helpEngine.fileData(name)
else:
return super().loadResource(_type, name)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.scene = QtWidgets.QGraphicsScene()
self.scene.setSceneRect(0, 0, 400, 200)
self.view = QtWidgets.QGraphicsView(self.scene)
self.view.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag)
self.view.setRenderHints(QtGui.QPainter.Antialiasing)
self.setCentralWidget(self.view)
self.createHelpWindow()
self.createActions()
self.createMenus()
self.createConnections()
self.setWindowTitle(self.tr("QGraphicsScene Help Example"))
self.resize(640, 480)
def createHelpWindow(self):
self.helpEngine = QtHelp.QHelpEngine(
os.path.join(CURRENT_DIR, "documentation", "qgraphicshelpexample.qhc")
)
self.helpEngine.setupData()
tWidget = QtWidgets.QTabWidget()
tWidget.setMaximumWidth(200)
tWidget.addTab(self.helpEngine.contentWidget(), "Contents")
tWidget.addTab(self.helpEngine.indexWidget(), "Index")
textViewer = HelpBrowser(self.helpEngine)
textViewer.setSource(
QtCore.QUrl("qthelp://walletfox.qt.helpexample/doc/index.html")
)
self.helpEngine.setUsesFilterEngine(True)
self.helpEngine.contentWidget().linkActivated.connect(textViewer.setSource)
self.helpEngine.indexWidget().linkActivated.connect(textViewer.setSource)
horizSplitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
horizSplitter.insertWidget(0, tWidget)
horizSplitter.insertWidget(1, textViewer)
horizSplitter.hide()
self.helpWindow = QtWidgets.QDockWidget(self.tr("Help"), self)
self.helpWindow.setWidget(horizSplitter)
self.helpWindow.hide()
self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.helpWindow)
def createActions(self):
self.insertEllipseAction = QtWidgets.QAction(self.tr("Insert &Ellipse"), self)
self.insertEllipseAction.setIcon(QtGui.QIcon(":/icons/ellipse.png"))
self.insertRectangleAction = QtWidgets.QAction(
self.tr("Insert &Rectangle"), self
)
self.insertRectangleAction.setIcon(QtGui.QIcon(":/icons/rectangle.png"))
self.helpAction = QtWidgets.QAction(self.tr("Help Contents..."), self)
self.helpAction.setShortcut(QtGui.QKeySequence.HelpContents)
self.aboutAction = QtWidgets.QAction(self.tr("&About"), self)
def createMenus(self):
self.itemMenu = QtWidgets.QMenu(self.tr("&Item"), self)
self.itemMenu.addAction(self.insertEllipseAction)
self.itemMenu.addAction(self.insertRectangleAction)
self.helpMenu = QtWidgets.QMenu(self.tr("&Help"), self)
self.helpMenu.addAction(self.helpAction)
self.helpMenu.addAction(self.aboutAction)
self.menuBar().addMenu(self.itemMenu)
self.menuBar().addMenu(self.helpMenu)
def insertItem(self):
action = self.sender()
if isinstance(action, QtWidgets.QAction):
itemToAdd = None
mPen = QtGui.QPen(QtCore.Qt.black, 3, QtCore.Qt.SolidLine)
eBrush = QtGui.QBrush(QtGui.QColor("#FF7F50"))
rBrush = QtGui.QBrush(QtGui.QColor("#CC0000"))
if action.iconText() == "Insert Ellipse":
itemToAdd = self.scene.addEllipse(0, 0, 150, 75, mPen, eBrush)
elif action.iconText() == "Insert Rectangle":
itemToAdd = self.scene.addRect(0, 0, 100, 100, mPen, rBrush)
if itemToAdd is not None:
itemToAdd.setFlags(
QtWidgets.QGraphicsItem.ItemIsSelectable
| QtWidgets.QGraphicsItem.ItemIsMovable
)
def about(self):
QtWidgets.QMessageBox.about(
self,
self.tr("About QGraphicsScene Help Example"),
self.tr(
"This example demonstrates how to implement\n"
"help for a Qt application."
),
)
def createConnections(self):
self.insertEllipseAction.triggered.connect(self.insertItem)
self.insertRectangleAction.triggered.connect(self.insertItem)
self.helpAction.triggered.connect(self.helpWindow.show)
self.aboutAction.triggered.connect(self.about)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_A:
for item in self.scene.selectedItems():
self.scene.removeItem(item)
else:
super().keyPressEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Note: Using the original file "qgraphicshelpexample.qhp" causes me errors since the "./foo" paths like "./insertobject.html" are not resolved correctly so I change them to "foo".
The complete example can be found here.

Why other window(GUI) is not opening while other window(GUI) is running in Python?

I have a scenario where one window is running in python Pyqt5. I want that when certain event happens another window also opens up.
I have written a code which I suppose should run fine but when event occurs to open other GUI, I gets an error.
My code:
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
app = QApplication(sys.argv)
win = QWidget()
l1 = QLabel("URL:")
url = QLineEdit()
l3 = QLabel("Wait (sec):")
wait = QLineEdit()
l2 = QLabel("Iteration:")
l2.move(20,100)
global add1
count = QLineEdit()
fbox = QFormLayout()
fbox.addRow(l1, url)
fbox.addRow(l3, wait)
vbox = QVBoxLayout()
vbox.addWidget(count)
fbox.addRow(l2, vbox)
startButton=QPushButton("Start")
fbox.addRow(startButton)
startButton.clicked.connect(self.requests)
win.setLayout(fbox)
win.setWindowTitle("--")
win.resize(300,200)
win.show()
sys.exit(app.exec_())
def requests(self):
for x in range(0,int(count.text())):
//certain event happens here, which will cause other window to get open
self.dialog = PopUp(self)
self.dialog.show()
def stop(self):
sys.exit()
class PopUp(QMainWindow):
def __init__(self, parent=None):
super(PopUp, self).__init__(parent)
app = QApplication(sys.argv)
win = QWidget()
l1 = QLabel("URL:")
nextUrl = QLineEdit()
fbox = QFormLayout()
fbox.addRow(l1, url)
startButton = QPushButton("Go")
fbox.addRow(startButton)
startButton.clicked.connect(self.requests)
win.setLayout(fbox)
win.setWindowTitle("--")
win.resize(300, 200)
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
I see that code is right but I am getting an unknown error:
QCoreApplication::exec: The event loop is already running
I have searched on google and here in stack overflow but didn't get anything worthy. Anyone knows that why this error comes and why is it coming in my code??
Each PyQt5 application must create one application object app = QApplication(sys.argv). Remove from the class MainWindow and the class PopUp - app = QApplication (sys.argv) .
sys.exit(app.exec_()) - the mainloop of the application, he must also be alone. Remove from the class MainWindow and the class PopUp - sys.exit(app.exec_())
I improved the readability of your example a bit.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class PopUp(QMainWindow):
def __init__(self, x, url, parent=None):
super(PopUp, self).__init__(parent)
self.url = url.text()
self.x = x + 1
self.setWindowTitle("-- PopUp {} --".format(self.x))
self.setGeometry(self.x*100, self.x*100, 300, 200)
win = QWidget()
self.setCentralWidget(win)
nextUrl = QLineEdit(self.url)
self.startButton = QPushButton("Go {}".format(self.x))
fbox = QFormLayout(win)
fbox.addRow(QLabel("URL:"), nextUrl)
fbox.addRow(self.startButton)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.dialogs = []
self.flag = False
win = QWidget()
self.setCentralWidget(win)
self.url = QLineEdit() # + self
wait = QLineEdit()
self.count = QLineEdit() # + self
startButton = QPushButton("Start")
startButton.clicked.connect(self.requests)
fbox = QFormLayout(win)
fbox.addRow(QLabel("URL:"), self.url)
fbox.addRow(QLabel("Wait (sec):"), wait)
fbox.addRow(QLabel("Iteration:"), self.count)
fbox.addRow(startButton)
def requests(self):
if self.dialogs and self.flag:
_ = [ i.hide() for i in self.dialogs]
self.dialogs = []
for x in range(0, int(self.count.text())):
# certain event happens here, which will cause other window to get open
dialog = PopUp(x, self.url, self)
dialog.startButton.clicked.connect(self.requests2)
dialog.show()
self.dialogs.append(dialog)
self.flag = True
def stop(self): # ?
sys.exit()
def requests2(self):
print("def requests2(self): clicked Button {}".format(self.sender().text()))
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.setWindowTitle("-- Title --")
main.resize(300,200)
main.show()
sys.exit(app.exec_())

TypeError: check() missing 1 required positional argument: 'theText'

I'm making a small PyQt4 application and so far I have this:
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.initUi()
def initUi(self):
self.setFixedSize(500, 300)
self.text = QtGui.QLabel('Text to be changed')
self.text2 = QtGui.QLabel('Also to be changed')
self.textCheckBox = QtGui.QCheckBox()
self.textCheckBox.stateChanged.connect(self.check(self.text))
self.show()
def check(self, state, theText):
if state == QtCore.Qt.Checked:
theText.setStyleSheet("color: pink")
else:
theText.setStyleSheet("color: black")
def main():
q = QtGui.QApplication(sys.argv)
w = Window()
sys.exit(q.exec())
if __name__=='__main__':
main()
The problem is, my .connect line doesn't seem to want to recognize the parameter I pass into it and I'm not sure why. I can't reference the text directly in the function as I would like to pass many QLabel arguments to it hence I made a theText parameter. I'd appreciate any help.
Version that works without parameters:
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.initUi()
def initUi(self):
self.setFixedSize(500, 300)
self.text = QtGui.QLabel('Text to be changed')
self.text2 = QtGui.QLabel('Also to be changed')
self.textCheckBox = QtGui.QCheckBox()
self.textCheckBox.stateChanged.connect(self.check)
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.text)
self.hbox.addWidget(self.textCheckBox)
self.setLayout(self.hbox)
self.show()
def check(self, state):
if state == QtCore.Qt.Checked:
self.text.setStyleSheet("color: pink")
else:
self.text.setStyleSheet("color: black")
def main():
q = QtGui.QApplication(sys.argv)
w = Window()
sys.exit(q.exec())
if __name__=='__main__':
main()
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.initUi()
def initUi(self):
self.setFixedSize(500, 300)
self.text = QtGui.QLabel('Text to be changed')
self.text2 = QtGui.QLabel('Also to be changed')
self.textCheckBox = QtGui.QCheckBox()
test = self.textCheckBox.checkState()
self.textCheckBox.stateChanged.connect(lambda: self.check(self.textCheckBox.checkState(), self.text))
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.text)
self.hbox.addWidget(self.textCheckBox)
self.setLayout(self.hbox)
self.show()
def check(self, state, theText):
if state == QtCore.Qt.Checked:
self.setWindowTitle("test")
else:
theText.setStyleSheet("color: black")
def main():
q = QtGui.QApplication(sys.argv)
w = Window()
sys.exit(q.exec())
if __name__=='__main__':
main()
Seem to have fixed it. Not too sure why it works though.

Writing a custom QPushButton class in Python

I've recently started learning PyQt on my own and I've come in some trouble trying to write a custom class that inherits from QPushButton so I can adjust its attributes. I'm trying to pass a text as an argument whenever I initialize an object of this class. I am pretty sure there's something wrong with my init but I haven't found it yet.
Here is the code:
import sys
from PySide import QtGui, QtCore
class mainb(QtGui.QPushButton):
def __init__(Text,self, parent = None):
super().__init__(parent)
self.setupbt(Text)
def setupbt(self):
self.setFlat(True)
self.setText(Text)
self.setGeometry(200,100, 60, 35)
self.move(300,300)
print('chegu aqui')
self.setToolTip('Isso é muito maneiro <b>Artur</b>')
self.show()
class mainwindow(QtGui.QWidget):
def __init__(self , parent = None):
super().__init__()
self.setupgui()
def setupgui(self):
self.setToolTip('Oi <i>QWidget</i> widget')
self.resize(800,600)
self.setWindowTitle('Janela do Artur')
af = mainb("Bom dia",self)
self.show()
"""
btn = QtGui.QPushButton('Botão',self)
btn.clicked.connect(QtCore.QCoreApplication.instance().quit)
btn.resize(btn.sizeHint())
btn.move(300, 50)
"""
def main():
app = QtGui.QApplication(sys.argv)
ex = mainwindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You are using super in wrong way, super must get a instance and another thing your first arg is Text, that's wrong that should be self. I fixed some more and the below code should work for you
import sys
from PySide import QtGui, QtCore
class mainb(QtGui.QPushButton):
def __init__(self, Text, parent = None):
super(mainb, self).__init__()
self.setupbt(Text)
def setupbt(self, Text):
self.setFlat(True)
self.setText(Text)
self.setGeometry(200,100, 60, 35)
self.move(300,300)
print('chegu aqui')
self.setToolTip('Isso muito maneiro <b>Artur</b>')
self.show()
class mainwindow(QtGui.QWidget):
def __init__(self , parent = None):
super(mainwindow, self).__init__()
self.setupgui()
def setupgui(self):
self.setToolTip('Oi <i>QWidget</i> widget')
self.resize(800,600)
self.setWindowTitle('Janela do Artur')
newLayout = QtGui.QHBoxLayout()
af = mainb("Bom dia",self)
newLayout.addWidget(af)
self.setLayout(newLayout)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = mainwindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Your def setupbt(self) does not seem to take the text as argument. Try def setupbt(self, Text): instead.

PyQT4: get values from another python module in parallel thread

Got some problem with PyQT and QThread.
When using method from another module in QThread run(), i can't get values from it.
How can i get them?
from PyQt4 import QtCore, QtGui
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.initAnotherThread()
self.setFixedSize(640, 360)
self.setWindowTitle('Window')
self.logText = QtGui.QTextEdit(self)
self.logText.setReadOnly(True)
self.logText.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.logText.resize(460, 330)
self.clickButton = QtGui.QPushButton('Click Button', self)
self.clickButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.clickButton.setGeometry(470, 50, 160, 35)
self.connect(self.clickButton, QtCore.SIGNAL('clicked()'), self.onButtonClick)
def initAnotherThread(self):
self.updaterThread = anotherThread(self)
def onButtonClick(self):
self.logText.clear()
self.updaterThread.start()
class anotherThread(QtCore.QThread):
def __init__(self, mw):
super(anotherThread, self).__init__(mw)
self.mw = mw
def run(self):
print "Another thread started"
AnotherModule.anotherMethod()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
In AnotherModule i have next:
anotherMethod():
x=0
while x<100:
x+=1
What should i do to get x value from AnotherModule?

Categories

Resources