So, I'm using Python and PyQt. I have a Main Window that contains a QTableWidget, and a dialog that opens modally and has some QLineEdit widgets... All right so far, but I have 2 problems:
When the dialog opens, my Main Window freezes, and I don't really like that...
What I want, when I finish editing a QLineEdit, is that the program will search the QTableWidget, and if the text from the QLineEdit exists in the table, a dialog will come up and informe about that. That's the general idea. But, so far, I seem to only be able to create a new QTableWidget instance, and I can't use the data from the existing...
What can I do about these?
You wrote:
and a dialog that opens modally
and then:
When the dialog opens, my Main Window freezes
The docs say:
int QDialog::exec () [slot]
Shows the dialog as a modal dialog,
blocking until the user closes it. The function returns a DialogCode
result. If the dialog is application modal, users cannot interact with
any other window in the same application until they close the dialog.
If the dialog is window modal, only interaction with the parent window
is blocked while the dialog is open. By default, the dialog is
application modal.
About modeless dialogs:
A modeless dialog is a dialog that operates independently of other
windows in the same application. Find and replace dialogs in
word-processors are often modeless to allow the user to interact with
both the application's main window and with the dialog.
Modeless
dialogs are displayed using show(), which returns control to the
caller immediately.
An example:
import sys
from PyQt4 import QtCore, QtGui
class SearchDialog(QtGui.QDialog):
def __init__(self, parent = None):
QtGui.QDialog.__init__(self, parent)
self.setWindowTitle('Search')
self.searchEdit = QtGui.QLineEdit()
layout = QtGui.QVBoxLayout()
layout.addWidget(self.searchEdit)
self.setLayout(layout)
class MainWindow(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self, None)
self.resize(QtCore.QSize(320, 240))
self.setWindowTitle('Main window')
self.logText = QtGui.QPlainTextEdit()
searchButton = QtGui.QPushButton('Search')
layout = QtGui.QVBoxLayout()
layout.addWidget(self.logText)
layout.addWidget(searchButton)
self.setLayout(layout)
searchButton.clicked.connect(self.showSearchDialog)
def showSearchDialog(self):
searchDialog = SearchDialog(self)
searchDialog.show()
searchDialog.searchEdit.returnPressed.connect(self.onSearch)
def onSearch(self):
self.logText.appendPlainText(self.sender().text())
def main():
app = QtGui.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
app.exec_()
if __name__ == "__main__":
main()
Click 'Search' to open a search window (you can open several of them). Enter a text to search and press Enter. The text to search will be added to the log in the main window.
Related
I need to execute a block of code when the user clicks on the tab of a tabbified QDockWidget. So far I've been doing this via a hack using the "visibilityChanged" event but this is now causing issues (for example, if I have several tabbified dock widgets and I drag one out so that it is floating, the tabbified one underneath will fire its "visibilityChanged" event which I will mistakenly interpret as the user clicking the tab). How can I receive proper notification when a user clicks on a QDockWidgets' tab? I've experimented with the "focusInEvent" of QDockWidget but it doesn't seem to fire when the tab is clicked.
When you use tabifyDockWidget() method QMainWindow creates a QTabBar, this is not directly accessible but using findChild() you can get it, and then use the tabBarClicked signal
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
first_dock = None
for i in range(10):
dock = QtGui.QDockWidget("title {}".format(i), self)
dock.setWidget(QtGui.QTextEdit()) # testing
self.addDockWidget(QtCore.Qt.TopDockWidgetArea, dock)
if first_dock:
self.tabifyDockWidget(first_dock, dock)
else:
first_dock = dock
dock.raise_()
tabbar = self.findChild(QtGui.QTabBar, "")
tabbar.tabBarClicked.connect(self.onTabBarClicked)
def onTabBarClicked(self, index):
tabbar = self.sender()
text = tabbar.tabText(index)
print("index={}, text={}".format(index, text))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I have two .py files created from .ui files made in QtDesigner. One is a main window for the program, and the other is a widget that allows users to input information and I'm calling it the "evaluation" widget.
I have a button in the main window called "btn_StartNew", which is meant to open the widget window to allow the user to start a new evaluation. I'm having troubles with opening the main window, and adding the function to the "btn_StartNew" button that opens the "evaluation" widget.
The code I have right now opens both the main window and the evaluation widget in the same window when I run the code:
import sys
from PyQt4 import QtCore, QtGui
from wid_Main import Ui_wid_Main
from wid_Eval_v2 import Ui_wid_Eval
class Win_Eval(QtGui.QWidget):
def __init__(self, parent=None):
super(Win_Eval, self).__init__(parent)
self.ui=Ui_wid_Eval()
self.ui.setupUi(self)
class Win_Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Win_Main, self).__init__(parent)
self.ui=Ui_wid_Main()
self.ui.setupUi(self)
#RUN "start new eval" button
self.ui.btn_StartNew.clicked.connect(self.btn_StartNew_click)
self.dialog = Win_Eval(self)
def btn_StartNew_click(self):
self.dialog.show()
def main():
app = QtGui.QApplication(sys.argv)
main = Win_Main()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Where wid_Main and Ui_wid_Main are the main window file and the main window class, respectively. And wid_Eval_v2 and Ui_wid_Eval are the evaluation widget file and class, respectively.
Any help would be much appreciated!
You must change:
self.dialog = Win_Eval(self)
to
self.dialog = Win_Eval()
I want to open a game application replacing the menu window.
So I have a game application which I can start with:
subprocess.call(["mygameprogram", "argument one"])
This opens up another window, but I want to replace the qt window with the game window without closing the menu window.
This is my MainWindow class:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initMenu()
self.show()
def initMenu(self):
# load ui file
uic.loadUi("somefile.ui", self)
# add pushbutton
btn = QPushButton()
# add click listener
btn.clicked.connect(self.startLevel)
# add button to layout
self.layout_buttons.addWidget(btn)
def startLevel(self):
# open game, put the right code in here :D
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())
Is there any solution for that? And if not, what should I do instead?
Thanks in advance
Hello I am working on data archive program with python 2.7. I have one mainWindow and there is some elements (Buttons, text lines etc.) Clicking a button open a dialog form page. User select their answer on that dialog page. Dialog page has a button named 'save'. When clicking save button dialog class saving user's selections to database. I want to do, when user clicked to save button on dialog, It will enable some elements on the mainWindow which is not enabled. I am doing this with these codes entering to dialog class and save button function:
self.ui.onceBut.setEnabled(True) etc.
But I am taking an error:
AttributeError: 'onceDlg' object has no attribute 'onceBut'
onceDlg is dialog pages class name.
How can I solve this and I can do what I want? Thanks in advance.
self in self.ui.onceBut.setEnabled(True) refers to dialog, so you get error because your onceBut is in your mainWindow not in onceDlg dialog.
Solution: as #Radio say - Communication between components in Qt are often done using signals and slots, but it's not the only way.
Easier way is to simply pass main window to dialog window, so you can manipulate with it's buttons, or whatever you want, inside dialog window. In next example I've done that in line dialog = Dialog(self), where self refers to MainWindow and it is used as mainWin inside Dialog. Run it, click on first button, dialog will show, click save button in dialog and second button in main will be changed and disabled.
I hope I've helped you.
import sys
from PyQt4 import QtCore, QtGui
class Dialog(QtGui.QDialog):
def __init__(self, mainWin):
QtGui.QDialog.__init__(self,mainWin)
self.setWindowTitle(self.tr("Dialog window"))
self.main = mainWin
button = QtGui.QPushButton()
button.setText( "Save (disable dummy button)" )
layout = QtGui.QVBoxLayout()
layout.addWidget(button)
self.setLayout(layout)
self.connect(button, QtCore.SIGNAL("clicked()"), self.save)
self.resize(200, 100)
def save(self):
self.main.button2.setEnabled(False)
self.main.button2.setText( "changed from dialog" )
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle(self.tr("Main window"))
self.button1 = QtGui.QPushButton()
self.button2 = QtGui.QPushButton()
self.button1.setText( "Open dialog" )
self.button2.setText( "Dummy" )
layout = QtGui.QVBoxLayout()
layout.addWidget(self.button1)
layout.addWidget(self.button2)
self.window = QtGui.QWidget()
self.window.setLayout(layout)
self.setCentralWidget(self.window);
self.connect(self.button1, QtCore.SIGNAL("clicked()"), self.showDialog)
self.resize(360, 145)
def showDialog(self):
dialog = Dialog(self)
dialog.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show();
sys.exit(app.exec_())
I need to know how to be able to make a dialog pop-up when a user clicks a button.
I'm relatively new to both Python and PyQt/QtDesigner. I've only been using in them for about a month, but I think I have a good grasp.
Here's what I have: A main dialog (which is the main part of the application), which I designed in QtDesigner. I converted the .ui to .py using pyuic4easy.
Here's what I want to do: design a new dialog box in the QtDesigner and somehow make it pop up when a user clicks a button on the first (main) dialog.
Here's the code for my main dialog:
import sys
from PyQt4.QtCore import *
from loginScreen import *
class MyForm(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL('clicked()'), self.popup)
...
... Some functions ...
def popup(self):
#Pop-up the new dialog
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp= MyForm()
myapp.show()
sys.exit(app.exec_())
So as you can see, I've connected the first button to a method named 'popup', which needs to be filled in with code to make my second window pop up. How do I go about doing this? Remember that I already have designed my second dialog in QtDesigner, and I don't need to create a new one.
Thanks for all the help!
So as you can see, I've connected the first button to a method named
'popup', which needs to be filled in with code to make my second
window pop up. How do I go about doing this?
Pretty much the same way you do it for your main window (MyForm).
As usual, you write a wrapper class for your QtDesigner code for the second dialog (like you did with MyForm). Let's call it MyPopupDialog. Then in your popup method, you create an instance and then show your instance with either exec_() or show() depending whether you want a modal or modeless dialog. (If you are not familiar with Modal/Modeless concept, you might refer to the documentation.)
So the overall thing might look like this (with a couple of modifications):
# Necessary imports
class MyPopupDialog(QtGui.QDialog):
def __init__(self, parent=None):
# Regular init stuff...
# and other things you might want
class MyForm(QtGui.QDialog):
def __init__(self, parent=None):
# Here, you should call the inherited class' init, which is QDialog
QtGui.QDialog.__init__(self, parent)
# Usual setup stuff
self.ui = Ui_Dialog()
self.ui.setupUi(self)
# Use new style signal/slots
self.ui.pushButton.clicked.connect(self.popup)
# Other things...
def popup(self):
self.dialog = MyPopupDialog()
# For Modal dialogs
self.dialog.exec_()
# Or for modeless dialogs
# self.dialog.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp= MyForm()
myapp.show()
sys.exit(app.exec_())