I have a scenario where I have a table and I want to display a list widget under a particular cell which I click.i am getting the click on cell in the first column and want to use on click on only first cell.(cell click is implemented here) . the only problem is how to display list under cell now.?!?!?!
Initial View
Final
My Code for Table is :-
from untitled import *
from PyQt4 import QtGui # Import the PyQt4 module we'll need
import sys # We need sys so that we can pass argv to QApplication
import os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtGui, QtCore
class MainWindow(QMainWindow,Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
self.tableWidget.clicked.connect(self.hello)
def hello(self,item):
#print(item.column())
if item.column()==0 :
print("success")
#I want to add this List at this cell of table
itemN = QtGui.QListWidget()
#hlayout = QtGui.QHBoxLayout()
#hlayout.addWidget(itemN)
#self.setCentralWidget(itemN)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Any help would be appreciated.
Thanks
my untitled.py code is here which generates a table in a window
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.tableWidget = QtGui.QTableWidget(self.centralwidget)
self.tableWidget.setObjectName(_fromUtf8("tableWidget"))
self.tableWidget.setColumnCount(4)
self.tableWidget.setRowCount(13)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(3, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(4, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(5, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(6, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(7, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(8, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(9, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(10, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(11, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(12, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 31))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(2)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(3)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(4)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(5)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(6)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(7)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(8)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(9)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(10)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(11)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.verticalHeaderItem(12)
item.setText(_translate("MainWindow", "New Row", None))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "a", None))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "b", None))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "New Column", None))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "d", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
To get the position of the current cell we use the columnViewportPosition() and rowViewportPosition() methods that return the position x, y of the row and column respectively with respect to the QTableWidget viewport(), then we get the global position using the mapToGlobal() method, we will add the height of the cell to move it vertically.
It creates a Popup for it is going to use a QDialog where the QListWidget will be placed, this widget returns the selected text.
class PopUp(QDialog):
def __init__(self, labels):
QDialog.__init__(self, None, Qt.Popup | Qt.FramelessWindowHint)
self.itemSelected = ""
self.setLayout(QVBoxLayout())
lWidget = QListWidget(self)
self.layout().addWidget(lWidget)
lWidget.addItems(labels)
lWidget.itemClicked.connect(self.onItemClicked)
self.layout().setContentsMargins(0, 0, 0, 0)
def onItemClicked(self, item):
self.itemSelected = item.text()
self.accept()
def text(self):
return self.itemSelected
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
self.tableWidget.clicked.connect(self.onClicked)
def onClicked(self, index):
row = index.row()
column = index.column()
x = self.tableWidget.columnViewportPosition(column)
y = self.tableWidget.rowViewportPosition(row) + self.tableWidget.rowHeight(row)
pos = self.tableWidget.viewport().mapToGlobal(QPoint(x, y))
p = PopUp(["1", "2", "3", "4", "5"])
p.move(pos)
if p.exec_() == QDialog.Accepted:
t_item = QTableWidgetItem(p.text())
self.tableWidget.setItem(row, column, t_item)
Screenshot:
I think the function you are looking for is:
self.tableWidget.setCellWidget(rowNum, colNum, itemN)
Where rowNum and colNum is the position, so 0,0 will put it in the upper left box. itemN is the QListWidget you made.
Here is a reference:
http://pyqt.sourceforge.net/Docs/PyQt4/qtablewidget.html#setCellWidget
And here is a related question: Adding widgets to qtablewidget pyqt
After looking at your screenshots I see the object you want is a QComboBox, not a QlistWidget.
Link: http://doc.qt.io/qt-4.8/qcombobox.html
You'll want to use the original function I mentioned to fill an element of the table with a combobox instead of a listWidget. And then use addItems to fill the combobox with options. And then use currentText to see what option the user has selected.
If that doesn't sound like what you want, you'll have to make a custom version of the tableWidget that has the functionality you want. That is more complicated and I can't cover that all in a single answer. But if you have more questions I can try to point you in the right direction.
Related
I want to create the basic look of my GUI with Qt-Designer, and add the functions via coding afterwards. Maybe there is already the Problem, but let's go on further.
My GUI that i created via Qt desinger consists of a 4x4 Table and a button.
When the Button is pressed, i want to write something in the cells of the Table.
(Sure, this in particular would be possible without using Qt desinger. But for the future there iwant to creat some more difficult GUIs. And therefore the Qt designer does save quite some time for a newbie like me :) )
The GUI code is:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(686, 539)
self.widget = QtWidgets.QWidget(Form)
self.widget.setGeometry(QtCore.QRect(10, 60, 258, 223))
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.tableWidget = QtWidgets.QTableWidget(self.widget)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(4)
self.tableWidget.setRowCount(4)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
self.verticalLayout.addWidget(self.tableWidget)
self.pushButton = QtWidgets.QPushButton(self.widget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
self.pushButton.clicked.connect(say_hello)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("Form", "1"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("Form", "2"))
item = self.tableWidget.verticalHeaderItem(2)
item.setText(_translate("Form", "3"))
item = self.tableWidget.verticalHeaderItem(3)
item.setText(_translate("Form", "4"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("Form", "A"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("Form", "B"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("Form", "C"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("Form", "D"))
testitem=QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(1, 0, testitem)
self.pushButton.setText(_translate("Form", "PushButton"))
self.pushButton.clicked.connect(say_hello(testitem))
def say_hello(testitem):
print("Hello you!")
testitem.setText("Hi")
the GUI gets called from another file like that:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication
import sys
import GUI_PyQtn
class ExampleApp(QtWidgets.QWidget, GUI_PyQtn.Ui_Form):
def __init__(self, parent=None):
super(ExampleApp, self).__init__(parent)
self.setupUi(self)
def main():
app = QApplication(sys.argv)
form = ExampleApp()
form.show()
app.exec_()
if __name__ == '__main__':
main()
My thoughts on my approach were, creating the Cell object and pass it to the function "say_hello". If the function would be inside the Ui_Form Class, it acutally called it not even once.
I believe you can get what you're looking for with the following tweaks.
Declare testitem with self in class Ui_Form
Declare say_hello in class Ui_Form
Pass testitem in say_hello by lambda
No use click.connect() in retranslateUi
that's it
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(686, 539)
self.widget = QtWidgets.QWidget(Form)
self.widget.setGeometry(QtCore.QRect(10, 60, 258, 223))
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.tableWidget = QtWidgets.QTableWidget(self.widget)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(4)
self.tableWidget.setRowCount(4)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
self.verticalLayout.addWidget(self.tableWidget)
self.pushButton = QtWidgets.QPushButton(self.widget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
# declare testitem with self ih here
self.testitem=QtWidgets.QTableWidgetItem()
# pass testitem in say_hello
self.pushButton.clicked.connect(lambda: self.say_hello(self.testitem))
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("Form", "1"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("Form", "2"))
item = self.tableWidget.verticalHeaderItem(2)
item.setText(_translate("Form", "3"))
item = self.tableWidget.verticalHeaderItem(3)
item.setText(_translate("Form", "4"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("Form", "A"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("Form", "B"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("Form", "C"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("Form", "D"))
#self.testitem=QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(1, 0, self.testitem)
#self.pushButton.setText(_translate("Form", "PushButton"))
#self.pushButton.clicked.connect(self.say_hello(testitem))
# say_hello in class
def say_hello(self, testitem):
testitem.setText('Hi')
I am using PyQt5 and i have a qtablewidget where i list the items from the database. Every item has an enter time and exit time but all the exit time is empty at first. I am using a logic like if exit time is empty show a button, but if not show the exit time. I can change the exit time with the button and i want the button to disappear after the change but button is not disappearing until i restart the program.
I have another button for editing the rows and i used it to understand the stuation and plug it to a function to change the exitTime to empty. if i click the edit exitTime changes to the empty and exit button comes back but i cant make the exit button go by clicking the exit
def loadData(self):
databse.connection
result = mcursor.fetchall()
row=0
self.ui.carList.setRowCount(len(result))
for r in result:
self.btn_sell = QtWidgets.QPushButton('Çıkış')
self.btn_sell.clicked.connect(self.handleButtonClicked)
self.btnEdit = QtWidgets.QPushButton('Düzenle')
self.btnEdit.clicked.connect(self.updateDialog)
self.ui.carList.setItem(row, 0, QtWidgets.QTableWidgetItem(r[1]))
self.ui.carList.setItem(row, 1, QtWidgets.QTableWidgetItem(r[2]))
self.ui.carList.setItem(row, 2, QtWidgets.QTableWidgetItem(r[3]))
self.ui.carList.setItem(row, 3, QtWidgets.QTableWidgetItem(r[5].strftime('%H:%M:%S %Y-%m-%d')))
if r[6].strftime('%Y-%m-%d %H:%M:%S') == "1000-01-01 00:00:00":
self.ui.carList.setCellWidget(row, 4, self.btn_sell)
else:
self.ui.carList.setItem(row, 4, QtWidgets.QTableWidgetItem(r[6].strftime('%H:%M:%S %Y-%m-%d')))
self.ui.carList.setCellWidget(row, 5, self.btnEdit)
row += 1
minimal reproducible example:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog, QMainWindow, QStyleFactory, QTabWidget, QInputDialog
from stack import Ui_MainWindow
from PyQt5.QtGui import QPixmap, QImage
import os
from datetime import datetime
def dbFunc(): # for creating the list for the first time
db = [["ahmet", "yıldırım", "KS67AEA", "23:09:39 2021-04-09", "23:09:39 2021-04-09"],
["mahmut", "celik", "TR67AKH", "23:09:39 2021-04-09", "1000-01-01 00:00:00"],
["mehmet", "gezen", "YU67OKY", "23:09:39 2021-04-09", "23:09:39 2021-04-09"],
["hakan", "duz", "PT67LDK", "23:09:39 2021-04-09", "1000-01-01 00:00:00"],
["ayse", "kavruk", "EO67KHL", "23:09:39 2021-04-09", "1000-01-01 00:00:00"]]
#print(db)
f = open("dbText.txt", "a")
for item in db:
for i in item:
f.write(i)
f.write(",")
f.write("\n")
f.close()
def toList():#read list
f = open("dbText.txt", "r")
dbList = f.read()
dbList = dbList.split("\n")
list = []
for i in dbList:
list.append(i.split(",")[:-1])
list.pop(-1)
f.close()
return list
def refreshFile(db):
os.remove('./dbText.txt')
f = open("dbText.txt", "a")
for item in db:
for i in item:
f.write(i)
f.write(",")
f.write("\n")
f.close()
class stapp(QMainWindow):
def __init__(self):
super(stapp, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.loadData()
#dbFunc() # for creating the list for the first time
dbList = toList()
def loadData(self):
result = self.dbList
row=0
self.ui.tableWidget.setRowCount(len(result))
for r in result:
self.btn_sell = QtWidgets.QPushButton('Çıkış')
self.btn_sell.clicked.connect(self.exit)
self.btnEdit = QtWidgets.QPushButton('Düzenle')
self.btnEdit.clicked.connect(self.updateDialog)
self.ui.tableWidget.setItem(row, 0, QtWidgets.QTableWidgetItem(r[0]))
self.ui.tableWidget.setItem(row, 1, QtWidgets.QTableWidgetItem(r[1]))
self.ui.tableWidget.setItem(row, 2, QtWidgets.QTableWidgetItem(r[2]))
self.ui.tableWidget.setItem(row, 3, QtWidgets.QTableWidgetItem(r[3]))
if r[4] == "1000-01-01 00:00:00":
self.ui.tableWidget.setCellWidget(row, 4, self.btn_sell)
else:
self.ui.tableWidget.setItem(row, 4, QtWidgets.QTableWidgetItem(r[4]))
self.ui.tableWidget.setCellWidget(row, 5, self.btnEdit)
row += 1
def exit(self):
button = QtWidgets.qApp.focusWidget()
index = self.ui.tableWidget.indexAt(button.pos())
if index.isValid():
result = self.dbList
now = datetime.now()
time = now.strftime('%Y-%m-%d %H:%M:%S')
result[index.row()][4] = time
refreshFile(self.dbList)
self.loadData()
def updateDialog(self):
button = QtWidgets.qApp.focusWidget()
index = self.ui.tableWidget.indexAt(button.pos())
if index.isValid():
result = self.dbList
time = "1000-01-01 00:00:00"
result[index.row()][4]=time
self.loadData()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QStyleFactory.create('GTK+'))
win = stapp()
win.show()
sys.exit(app.exec_())
Uİ:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(424, 279)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(10, 10, 401, 221))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(6)
self.tableWidget.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(5, item)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 424, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "name"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "surname"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "enterTime"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "exitTime"))
item = self.tableWidget.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "exit"))
item = self.tableWidget.horizontalHeaderItem(5)
item.setText(_translate("MainWindow", "edit"))
I'm new to PyQt5 and I'm using Qtdesigner to develop an interface.
I am controlling the number of rows of a Table Widget from the spinbox. However, when changing the number of rows I need to keep the check option for column a.
I managed to change the number of rows according to valueChanged in the spinbox, but the loop I created to create the check regardless of the number of rows did not work.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(519, 468)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.spinBox = QtWidgets.QSpinBox(self.centralwidget)
self.spinBox.setGeometry(QtCore.QRect(80, 131, 41, 31))
self.spinBox.setProperty("value", 2)
self.spinBox.setObjectName("spinBox")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(160, 80, 341, 101))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(2)
self.tableWidget.setRowCount(2)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
self.tableWidget.setItem(0, 0, item)
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
self.tableWidget.setItem(1, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(1, 1, item)
self.tableWidget.verticalHeader().setVisible(False)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 519, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.spinBox.valueChanged['int'].connect(self.tableWidget.setRowCount)
for i in range(self.tableWidget.rowCount()):
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
self.tableWidget.setItem(i, 0, item)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "d"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("MainWindow", "e"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "a"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "c"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
self.tableWidget.setSortingEnabled(__sortingEnabled)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "d"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("MainWindow", "e"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "a"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "c"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
self.tableWidget.setSortingEnabled(__sortingEnabled)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
First of all, it seems like you're editing the output of a pyuic generated file, or you're trying to mimic its behavior. In any case, this is something that should never be done.
Those files are meant to be left as they are, and you should only use them as modules; to know how to correctly do this, read more about using Designer. If you're trying to mimic their behavior, well, you shouldn't: the way pyuic files are treated is only considered as an "interpretation layer" in order to create the GUI objects and make them accessible from python. If you're building the GUI from code, just subclass the QWidget you want to use (QWidget, QDialog or QMainWindow, usually).
Now, the problem is that whenever setRowCount() is called...:
[it] Sets the number of rows in this table's model to rows. If this is less than rowCount(), the data in the unwanted rows is discarded.
This obviously means that, if you're removing rows, you're losing all items in that row (including the fact that they are checkable at all).
To correctly update the contents and add checkable items, you'll need to do that in a specific method that dynamically removes or adds items.
In the next example I'll show how to correctly implement this (and in an easier, clearer way):
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
central = QtWidgets.QWidget()
self.setCentralWidget(central)
layout = QtWidgets.QHBoxLayout(central)
self.spin = QtWidgets.QSpinBox()
layout.addWidget(self.spin)
self.table = QtWidgets.QTableWidget(2, 2)
layout.addWidget(self.table)
self.table.verticalHeader().setVisible(False)
for col, label in enumerate(('a', 'c')):
header = QtWidgets.QTableWidgetItem(label)
self.table.setHorizontalHeaderItem(col, header)
if col:
continue
for row in range(self.table.rowCount()):
item = QtWidgets.QTableWidgetItem()
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setCheckState(QtCore.Qt.Checked)
self.table.setItem(row, col, item)
self.spin.setValue(self.table.rowCount())
self.spin.valueChanged.connect(self.setRowCount)
def setRowCount(self, count):
if count == self.table.rowCount():
return
# if there are too many rows, remove them
while self.table.rowCount() > count:
self.table.removeRow(self.table.rowCount() - 1)
# if rows are going to be added, create checkable items for them
while self.table.rowCount() < count:
row = self.table.rowCount()
self.table.insertRow(row)
item = QtWidgets.QTableWidgetItem()
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setCheckState(QtCore.Qt.Checked)
self.table.setItem(row, 0, item)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
test = MainWindow()
test.show()
sys.exit(app.exec_())
As a side note, a couple of considerations:
a layout manager should always be used for widgets, otherwise the contents might become invisible or won't adjust their position;
you're defining retranslateUi twice; I suppose that's something that remained from editing the pyuic file, but, in any case, redifining a function with the same name results in overwriting it (unless each of them have an unique decorator)
Is it possible to create a switch button with pyqt5?
I'm designing a filtering tool in python using pyqt5. The user is supposed to be able to apply a filter or its complement on some data and even combine filters.
I display possible filters in qtablewidget where the user can choose filters to apply using checkboxes. In each row, checkboxes are exclusives i.e. the user can not select a filter and its complement at the same time.
But the problem is that once we select a checkbox in a row, we cannot deselect it unless we select its opposite.
In fact, when the filters are just loaded , all the boxes are unchecked (they are empty in a way) so I can choose which filter to apply but when I want to choose an other filter, one of the boxes of the precedent filter still checked (either box Filter or box Complement is checked) and I can not switch it off.
That's why I thought about adding a switch button in each row to disable a filter. By doing this I will be able to take in consideration or not the checked attribute.
Here is an example of what I want :
Below an reproductible example
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(550, 350)
MainWindow.setMinimumSize(QtCore.QSize(550, 350))
MainWindow.setMaximumSize(QtCore.QSize(550, 350))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(20, 20, 500, 200))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(3)
self.tableWidget.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
self.pushButton_Save = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_Save.setGeometry(QtCore.QRect(120, 250, 100, 50))
self.pushButton_Save.setMinimumSize(QtCore.QSize(100, 50))
self.pushButton_Save.setMaximumSize(QtCore.QSize(100, 50))
self.pushButton_Save.setObjectName("pushButton_Save")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 550, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "Name"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "Filter"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "complement"))
self.pushButton_Save.setText(_translate("MainWindow", "Save"))
self.pushButton_Save.clicked.connect(self.bindSave)
def bindSave(self):
numRows = self.tableWidget.rowCount()
self.tableWidget.insertRow(numRows)
groupButton = QtWidgets.QButtonGroup(self.tableWidget)
groupButton.setExclusive(True)
it1 = QtWidgets.QTableWidgetItem("filter "+str(numRows))
self.tableWidget.setItem(numRows, 0, it1)
ch_bx1 = QtWidgets.QCheckBox()
groupButton.addButton(ch_bx1)
self.tableWidget.setCellWidget(numRows, 1, ch_bx1)
ch_bx2 = QtWidgets.QCheckBox()
groupButton.addButton(ch_bx2)
self.tableWidget.setCellWidget(numRows, 2, ch_bx2)
if __name__ == "__main__":
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
Like others have suggested, you could enable/disable filters by adding a third column to the table and setting each item widget in this column to a like you did for ch_box1 and ch_box2. You can use slots and signals to manipulate the check buttons (for example enable/disable them depending on the state of the switch).
To create custom switches like in the picture in the OP, you could sub-class QPushButton and overriding paintEvent, e.g. (note that I've omitted the code that was the same as the code in the reproducable example in the original post)
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QRect
import sys
class MySwitch(QtWidgets.QPushButton):
def __init__(self, parent = None):
super().__init__(parent)
print('init')
self.setCheckable(True)
self.setMinimumWidth(66)
self.setMinimumHeight(22)
def paintEvent(self, event):
label = "ON" if self.isChecked() else "OFF"
bg_color = Qt.green if self.isChecked() else Qt.red
radius = 10
width = 32
center = self.rect().center()
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.translate(center)
painter.setBrush(QtGui.QColor(0,0,0))
pen = QtGui.QPen(Qt.black)
pen.setWidth(2)
painter.setPen(pen)
painter.drawRoundedRect(QRect(-width, -radius, 2*width, 2*radius), radius, radius)
painter.setBrush(QtGui.QBrush(bg_color))
sw_rect = QRect(-radius, -radius, width + radius, 2*radius)
if not self.isChecked():
sw_rect.moveLeft(-width)
painter.drawRoundedRect(sw_rect, radius, radius)
painter.drawText(sw_rect, Qt.AlignCenter, label)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
....
self.tableWidget.setColumnCount(4)
....
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
...
def retranslateUi(self, MainWindow):
...
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "status"))
def bindSave(self):
...
ch_bx3 = MySwitch()
ch_bx3.setChecked(True)
ch_bx3.clicked.connect(ch_bx1.setEnabled)
ch_bx3.clicked.connect(ch_bx2.setEnabled)
self.tableWidget.setCellWidget(numRows, 3, ch_bx3)
if __name__ == "__main__":
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
app.exec()
Screenshot:
I have a dialog designed in Qt Designer and set as non-modal that when launched is always modal. I am using OS X El Capitan, Python 3.5.1, Qt 5.4.2, pyqt4.
These code snippets show what I am doing:
Designer .ui code converted to python using pyuic.
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_purchaseInfoDialog(object):
def setupUi(self, purchaseInfoDialog):
purchaseInfoDialog.setObjectName(_fromUtf8("purchaseInfoDialog"))
purchaseInfoDialog.setWindowModality(QtCore.Qt.NonModal)
purchaseInfoDialog.resize(837, 377)
purchaseInfoDialog.setSizeGripEnabled(True)
purchaseInfoDialog.setModal(False)
self.purchaseInfoButtonBox = QtGui.QDialogButtonBox(purchaseInfoDialog)
self.purchaseInfoButtonBox.setGeometry(QtCore.QRect(710, 330, 101, 32))
self.purchaseInfoButtonBox.setOrientation(QtCore.Qt.Horizontal)
self.purchaseInfoButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Close)
self.purchaseInfoButtonBox.setObjectName(_fromUtf8("purchaseInfoButtonBox"))
self.purchaseInfoTable = QtGui.QTableWidget(purchaseInfoDialog)
self.purchaseInfoTable.setGeometry(QtCore.QRect(10, 50, 911, 271))
self.purchaseInfoTable.setObjectName(_fromUtf8("purchaseInfoTable"))
self.purchaseInfoTable.setColumnCount(9)
self.purchaseInfoTable.setRowCount(0)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(3, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(4, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(5, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(6, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(7, item)
item = QtGui.QTableWidgetItem()
self.purchaseInfoTable.setHorizontalHeaderItem(8, item)
self.piPartLabel = QtGui.QLabel(purchaseInfoDialog)
self.piPartLabel.setGeometry(QtCore.QRect(20, 20, 71, 16))
self.piPartLabel.setObjectName(_fromUtf8("piPartLabel"))
self.piPartdescriptionLabel = QtGui.QLabel(purchaseInfoDialog)
self.piPartdescriptionLabel.setGeometry(QtCore.QRect(120, 20, 191, 16))
self.piPartdescriptionLabel.setObjectName(_fromUtf8("piPartdescriptionLabel"))
self.poFromSelectionPushButton = QtGui.QPushButton(purchaseInfoDialog)
self.poFromSelectionPushButton.setGeometry(QtCore.QRect(540, 330, 171, 32))
self.poFromSelectionPushButton.setObjectName(_fromUtf8("poFromSelectionPushButton"))
self.retranslateUi(purchaseInfoDialog)
QtCore.QObject.connect(self.purchaseInfoButtonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), purchaseInfoDialog.accept)
QtCore.QObject.connect(self.purchaseInfoButtonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), purchaseInfoDialog.reject)
#QtCore.QObject.connect(self.poFromSelectionPushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), purchaseInfoDialog.poFromSelection)
QtCore.QMetaObject.connectSlotsByName(purchaseInfoDialog)
def retranslateUi(self, purchaseInfoDialog):
purchaseInfoDialog.setWindowTitle(_translate("purchaseInfoDialog", "Purchase History", None))
item = self.purchaseInfoTable.horizontalHeaderItem(0)
item.setText(_translate("purchaseInfoDialog", "#", None))
item = self.purchaseInfoTable.horizontalHeaderItem(1)
item.setText(_translate("purchaseInfoDialog", "P.O. #", None))
item = self.purchaseInfoTable.horizontalHeaderItem(2)
item.setText(_translate("purchaseInfoDialog", "Vendor", None))
item = self.purchaseInfoTable.horizontalHeaderItem(3)
item.setText(_translate("purchaseInfoDialog", "P.O. Date", None))
item = self.purchaseInfoTable.horizontalHeaderItem(4)
item.setText(_translate("purchaseInfoDialog", "Mfg", None))
item = self.purchaseInfoTable.horizontalHeaderItem(5)
item.setText(_translate("purchaseInfoDialog", "Mpn", None))
item = self.purchaseInfoTable.horizontalHeaderItem(6)
item.setText(_translate("purchaseInfoDialog", "Qty", None))
item = self.purchaseInfoTable.horizontalHeaderItem(7)
item.setText(_translate("purchaseInfoDialog", "Price", None))
item = self.purchaseInfoTable.horizontalHeaderItem(8)
item.setText(_translate("purchaseInfoDialog", "Dock", None))
self.piPartLabel.setText(_translate("purchaseInfoDialog", "Part", None))
self.piPartdescriptionLabel.setText(_translate("purchaseInfoDialog", "Description", None))
self.poFromSelectionPushButton.setText(_translate("purchaseInfoDialog", "P.O. From Selection", None))
I sub-class the designer class
#
# PURCHASE INFO (HISTORY) Dialog
#
# Sub-class Ui_purchaseInfoDialog
class PurchaseInfoDialog(QDialog, Ui_purchaseInfoDialog):
def __init__(self):
QDialog.__init__((self))
self.setModal(False)
Commented code below shows attempts to make it non-modal even though it should be. Nothing works.
self.ui.orderPartButton.clicked.connect(lambda: self.orderPartButtonClicked())
#
# Parts Slots
#
#
#pyqtSlot()
def orderPartButtonClicked(self):
selectedPart = MainWindow.ui.partShortagesTable.selectedItems()
if (selectedPart):
part = selectedPart[0].text()
aPurchaseInfoDialog = PurchaseInfoDialog()
pidUi = Ui_purchaseInfoDialog()
pidUi.setupUi(aPurchaseInfoDialog)
refreshPurchaseInfoTable(self, pidUi.purchaseInfoTable, pidUi.piPartLabel, pidUi.piPartdescriptionLabel, part, pathToArchive)
#aPurchaseInfoDialog.setWindowModality(QtCore.Qt.NonModal)
result = aPurchaseInfoDialog.exec_() # Launch the Purchase Info Dialog. result = 0 for Close
#aPurchaseInfoDialog.show()
Is there a problem with pyqt4 in my environment (I tried this under Linux with the same result) or am I missing some setting somewhere?
Demo:
import sys
from PyQt4 import QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Dialog1(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setModal(True)
class Dialog2(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setModal(False)
def window():
app = QApplication(sys.argv)
w = QWidget()
b = QPushButton(w)
b.setText("Modal Dialog")
b.move(15, 25)
b.clicked.connect(showdialog1)
c = QPushButton(w)
c.setText("Modless Dialog")
c.move(15, 75)
c.clicked.connect(showdialog2)
w.setWindowTitle("PyQt Dialog demo")
w.resize(200, 150)
w.show()
sys.exit(app.exec_())
def showdialog1():
# d = QDialog()
d = Dialog1()
#d.setWindowModality(QtCore.Qt.Modal)
b1 = QPushButton("Modal Dialog", d)
b1.move(50, 50)
d.setWindowTitle("Modal Dialog")
d.setWindowModality(Qt.ApplicationModal)
d.exec_()
def showdialog2():
# d = QDialog()
d = Dialog2()
d.setWindowModality(QtCore.Qt.NonModal)
b1 = QPushButton("ok", d)
b1.move(50, 50)
d.setWindowTitle("Modeless Dialog")
d.setWindowModality(Qt.ApplicationModal)
d.exec_()
if __name__ == '__main__':
window()
I rearranged some of your code because of personal preference (I'm sure you can put it back no problem), and now one is modal, and the other is nonmodal.
When you create a nonmodal window, you must provide a parent QWidget in the instantiation of the QDialog class. Then, instead of using QDialog.exec_(), use QDialog.show(). This shows the nonmodal window but allows the original parent to keep running, in a sense. Using exec_() will always result in a modal window, even if you set it to nonmodal. Here's the documentation: http://pyqt.sourceforge.net/Docs/PyQt4/qdialog.html
Here is the code:
class Dialog1(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setModal(True)
class Dialog2(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
self.setModal(0)
b1 = QPushButton("ok", self)
b1.move(50, 50)
b1.clicked.connect(self.exit)
self.setWindowTitle("Nonmodal Dialog")
self.show()
def exit(self):
self.close()
def window():
app = QApplication(sys.argv)
w = QWidget()
b = QPushButton(w)
b.setText("Modal Dialog")
b.move(15, 25)
b.clicked.connect(showdialog1)
c = QPushButton(w)
c.setText("Nonmodal Dialog")
c.move(15, 75)
c.clicked.connect(lambda: showdialog2(w))
w.setWindowTitle("PyQt Dialog demo")
w.resize(200, 150)
w.show()
sys.exit(app.exec_())
def showdialog1():
# d = QDialog()
d = Dialog1()
#d.setWindowModality(QtCore.Qt.Modal)
b1 = QPushButton("Modal Dialog", d)
b1.move(50, 50)
d.setWindowTitle("Modal Dialog")
d.setWindowModality(Qt.ApplicationModal)
d.exec_()
def showdialog2(w):
# d = QDialog()
Dialog2(w)
if __name__ == '__main__':
window()