A simple GUI with pyQT does not work. Why? - python

I have written the following python pyQT code to run a simple dialog application. However that does not work.
I'm using PyQT 5.0 on Win 8 64BIT.
It simply does not work and no error is returned.
When I run it, the current IDE (which is pycharm) gets blurred (which happens when a new windows is shown generally), though, no window is shown, and when I stop the execution, it returns -1. Here is my code:
from __future__ *
from sys import *
from math import *
from PyQT5.QtCore import *
from PyQT5.QtGui import *
from PyQT5.QtWidgets import *
class Form (QGuiDialog) :
def __init__(self, parent=None) :
super(Form, self).__init__(parent)
self.browser = QTextBrowser()
self.lineedit = QLineEdit("Type an Expression, then Press Enter")
self.lineedit.selectAll()
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit.setFocus()
self.connect(self.lineedit, SIGNAL("returnPressed()"), self.updateGui)
self.setWindowTitle("Calculate")
def updateGui (self) :
try :
text = unicode(self.lineedit.txt())
self.browser.append("%s = <b>%s<b>" % (text, eval(text)))
except :
self.browser.append("%s is an invalid expression" % (text))
app = QCoreApplication(sys.agrv)
x = Form()
x.show()
app.exec_()

It is my understanding that PyQT5 does not support SIGNALs and SLOTS used in PyQT4.
Therefore I think you might try a different way instead of SIGNAL for your lineedit.
Instead of:
self.connect(self.lineedit, SIGNAL("returnPressed()"), self.updateGui)
try
self.lineedit.textChanged.connect(self.updateGui)
Also I would suggest reading here the differences between PyQT5 and PyQT4 http://pyqt.sourceforge.net/Docs/PyQt5/pyqt4_differences.html
and check in the PyQT5 folder on your drive for extremely useful samples.

You have several problems in your code, I will address just some of them:
In order to actually see something with Qt you need to create a QApplication not a QCoreApplication.
You must fix the imports in the the line: from __future__ *.
On updateGui you need to initialize text if you want the exception handler to work fine.
Finally this is a working example of your code:
NOTE: I don't have PyQt5 just PyQt4, but I'm sure you'll get the idea ;)
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Form (QDialog) :
def __init__(self, parent=None) :
super(Form, self).__init__(parent)
self.browser = QTextBrowser()
self.lineedit = QLineEdit("Type an Expression, then Press Enter")
self.lineedit.selectAll()
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit.setFocus()
self.connect(self.lineedit, SIGNAL("returnPressed()"), self.updateGui)
self.setWindowTitle("Calculate")
def updateGui(self):
text = self.lineedit.text()
self.lineedit.clear()
try :
text = unicode(text)
self.browser.append("%s = <b>%s<b>" % (text, eval(text)))
except :
self.browser.append("<font color=red>%s</font> is an invalid expression" % (text))
app = QApplication(sys.argv)
x = Form()
x.show()
app.exec_()

Related

Cannot automatically close second window with QInputDialog

Issue in my code sample:
On "Select..." the selection dialog appears and works basically, but closing it with "Ok" or "Cancel", unfortunately leaves a second window open (title "New Popup"), which is very ugly... :/ I am searching for the way to close that automatically after the user applied the selection in the list, returning to the main window (and the data processing should still work of course).
Thanks for any help! :)
Background: Inside a basic pyqt5 window application, I created a simple list selection as a second (popup) window (separate class), where the user can select an item and the result is then processed in the main window class.
That works basically but I've got an issue with correctly closing the popup window and I was not able to find a solution since hours... Basically I tried self.close, self.destroy, self.hide etc. but nothing had an effect, probably I am missing a piece.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import QTimer
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QLineEdit, QInputDialog, QLabel, QVBoxLayout
class PopupDialog(QtWidgets.QDialog):
def __init__(self):
super(PopupDialog, self).__init__()
self.selected_item = None
layout = QtWidgets.QFormLayout()
self.setLayout(layout)
self.setWindowTitle("New Popup")
self.setMinimumWidth(400)
items = ("C", "C++", "Java", "Python")
item, ok = QInputDialog.getItem(self, "select input dialog",
"list of languages", items, 0, False)
self.selected_item = item
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.setMinimumWidth(600)
self.setWindowTitle("Main Window")
self.le = QtWidgets.QLineEdit()
button = QtWidgets.QPushButton("Select...")
button.clicked.connect(self.get_input)
layout = QtWidgets.QHBoxLayout()
layout.addWidget(self.le)
layout.addWidget(button)
self.setLayout(layout)
def get_input(self):
popup = PopupDialog()
popup.exec_()
print("got selection data: ", popup.selected_item)
self.le.setText(popup.selected_item)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

Python PyQt Change layout of combobox

Is there a way (or maybe a different widget i can use (i couldn't find any) so that i can make my combobox look something like the combobox in the picture ?
The picture shows what i want put with font. I would like the options to be my list instedt of the font.
I would like to see all the option (if there are to many to be able to scroll) and select one.
Here is my code so far:
from PyQt5 import QtCore, QtWidgets
import sys
from PyQt5 import QtGui, QtWidgets, QtPrintSupport
class Thired(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Thired, self).__init__(parent)
self.bb = QtWidgets.QComboBox(self)
self.bb.setGeometry(QtCore.QRect(212, 50, 400, 25))
self.bb.setEditable(True)
bpas = ['a','b','c']
self.bb.addItem("")
self.bb.setItemText(0, "")
for bpa in bpas:
self.bb.addItem(bpa)
self.bb.move(50, 200)
self.bb.activated[str].connect(self.style_choice)
def font_choice(self):
font, valid = QtWidgets.QFontDialog.getFont()
if valid:
self.styleChoice.setFont(font)
def style_choice(self, text):
self.styleChoice.setText(text)
QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create(text))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = Thired()
gui.show()
app.exec_()
Edit:
I would like that when the whindow opens that all my option are always beeing shown. So that i do not have to press the dropdown arror. In different words: If the window is beeing opened there is a list of bpas, i want to be able to select from the list one of the bpa/option and send a singal that i choose this bpa.
To explain myself a little more (this is not been shown anywhere in the code): bpas = ['a','b','c'] are projects, and I want the user to seleced one of them and after selecting it the programm will load its conneced database. With dropdown it works, but i dont like the way dorpdown looks like with a lot of options :)
You can use a QListWidget with a QLineEdit:
from PyQt5 import QtCore, QtWidgets
import string
class Thired(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Thired, self).__init__(parent)
self.line_edit = QtWidgets.QLineEdit()
self.list_widget = QtWidgets.QListWidget()
options = list(string.ascii_letters)
self.list_widget.addItems(options)
self.list_widget.itemClicked.connect(self.on_itemClicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.line_edit)
lay.addWidget(self.list_widget)
self.resize(640, 480)
#QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
def on_itemClicked(self, item):
self.line_edit.setText(item.text())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
gui = Thired()
gui.show()
sys.exit(app.exec_())

How to wait for user input in PyQt with Line Edit?

I'm working on a project of "wrapping" a program I built with PyQt GUI and I'm stuck with a basic thing.
I want the program to stop procceeding with the code and wait for my input, just like raw_input(). Here is my code:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class myWidget(QDialog):
def __init__(self,parent=None):
super(myWidget, self).__init__(parent)
self.lineEdit = QLineEdit()
self.textBrowser = QTextBrowser()
self.top_btn = QPushButton("Ask me")
self.bottom_btn = QPushButton("disable")
layout = QVBoxLayout()
layout.addWidget(self.textBrowser)
layout.addWidget(self.lineEdit)
layout.addWidget(self.top_btn)
layout.addWidget(self.bottom_btn)
self.setLayout(layout)
self.lineEdit.setDisabled(True)
self.lineEdit.clear()
self.connect(self.top_btn, SIGNAL("clicked()"), self.inputFunc)
self.connect(self.bottom_btn, SIGNAL("clicked()"), self.disableLine)
def inputFunc(self):
self.lineEdit.clear()
self.lineEdit.setDisabled(False)
self.textBrowser.setText("Welcome to #1 button. what do you want to do?")
userInput = self.lineEdit.text()
if userInput == "anything":
self.textBrowser.append("Ok i will leave you alone")
exit()
else:
self.textBrowser.append("say what?")
def disableLine(self):
self.lineEdit.clear()
self.textBrowser.append("Line edit is disabled")
self.lineEdit.setDisabled(True)
app = QApplication(sys.argv)
form = myWidget()
form.show()
app.exec_()
As you can see, there is a Line Edit and its variable. But it doesn't wait for my input, it proceed with the code and of course it doesn't let me to change the result of my "if" statement.
How do I pause the code and wait for the user input so my "if" statement result will be changed just like raw_input()? (if possible, without adding any new layouts.)
Thank you.
Structured programming has a different paradigm than event-oriented programming, GUIs use events to warn the slots that should perform that task.
In your case, the processing part must be done in another method and called when a signal is issued
For your case the QLineEdit widget has 2 signals that could serve you, the first one is editingFinished, and the second is returnPressed, in this case I choose the second that is emitted when I press the enter or return key. Then we connect that signal with the called process slot, that executes the task.
I made some changes that do not affect the design, first change the base class from QDialog to QWidget, in addition to the style of connection between the signals and the slots. If you want to close the window you must use close()
complete code:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class myWidget(QWidget):
def __init__(self,parent=None):
super(myWidget, self).__init__(parent)
self.lineEdit = QLineEdit()
self.textBrowser = QTextBrowser()
self.top_btn = QPushButton("Ask me", )
self.bottom_btn = QPushButton("disable")
layout = QVBoxLayout()
layout.addWidget(self.textBrowser)
layout.addWidget(self.lineEdit)
layout.addWidget(self.top_btn)
layout.addWidget(self.bottom_btn)
self.setLayout(layout)
self.lineEdit.setDisabled(True)
self.top_btn.clicked.connect(self.inputFunc)
self.lineEdit.returnPressed.connect(self.process)
#self.bottom_btn.clicked.connect(self.disableLine)
def inputFunc(self):
self.lineEdit.setDisabled(False)
self.textBrowser.setText("Welcome to #1 button. what do you want to do?")
def process(self):
userInput = self.lineEdit.text()
if userInput == "anything":
self.textBrowser.append("Ok i will leave you alone")
#self.close()
else:
self.textBrowser.append("say what?")
self.lineEdit.clear()
app = QApplication(sys.argv)
w = myWidget()
w.show()
sys.exit(app.exec_())

A QApplication instance already exists

I'm doing some simple PySide on 3Dsmax 2015.
This is my error:
python.ExecuteFile "C:\Program Files\Autodesk\3ds Max 2015\scripts\Python\demoUniTest.py"
-- Runtime error: Line 32 <module>()
<type 'exceptions.RuntimeError'> A QApplication instance already exists.
This is my code:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from math import *
class Form(QDialog):
def __init__(self,parent=None):
super(Form,self).__init__(parent)
self.browser = QTextBrowser()
self.lineedit = QLineEdit("Type an expression and press Enter")
self.lineedit.selectAll()
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit.setFocus()
self.connect(self.lineedit, SIGNAL("returnPressed()"),self.updateUi)
self.setWindowTitle("Calculate")
def updateUi(self):
try:
text = self.lineedit.text()
self.browser.append("%s = <b>%s</b>" % (text,eval(text)))
except:
self.browser.append("<font color=red>%s is invalid</font>" %text)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
When I use this code on Pycharm,I don't get any errors. It only appears when I use it on 3Dsmax 2015 Listener
Direct citation from the helpfile (Using PySide):
Normally one creates a PySide application object in a script using
QtGui.QApplication(). However, in 3ds Max, there is already a PySide
application running, so you get a handle for that object like this:
QtGui.QApplication.instance()
As a note this has changed somewhat in 3DS Max 2018 and PySide2. I'm just playing around with it myself right now and I was able to get it working after a bit of tinkering. Here's a link to the documentation, though be warned that there is a small typo in the code (at least at the time of writing): http://help.autodesk.com/view/3DSMAX/2018/ENU/?guid=__developer_what_s_new_in_3ds_max_python_api_what_s_new_in_the_3ds_max_2018_p_html
As mentioned in other answers you need to make your UI a child of the main 3DS Max application. The good news is that they have simplified this a bit for you with the function GetQMaxMainWindow(). Use it like this:
from PySide2 import QtWidgets, QtCore, QtGui
import MaxPlus
import os
class SampleUI(QtWidgets.QDialog):
def __init__(self, parent=MaxPlus.GetQMaxMainWindow()):
super(SampleUI, self).__init__(parent)
self.initUI()
def initUI(self):
mainLayout = QtWidgets.QHBoxLayout()
testBtn = QtWidgets.QPushButton("Test!")
mainLayout.addWidget(testBtn)
self.setLayout(mainLayout)
if __name__ == "__main__":
try:
ui.close()
except:
pass
ui = SampleUI()
ui.show()
You're creating an instance of QApplication in the line:
app = QApplication(sys.argv)
And getting that error because there's another instance of QApplication created somewhere before that (presumably somewhere in "3Dsmax 2015 Listener") and you're only allowed one.
See:
QT documentation on QApplication

PyQt4 Python Gui Coding: Request for help debugging syntax error

I am learning PyQt4 and have written a simple expression evaluator. I am having difficulty debugging the second to last line of my init function (self.connect..... ). Python returns 'syntax error' but I can't spot the problem. I'd appreciate any help you can offer pointing it out. I am using Python 2.7.6 on Ubuntu 13.10 Linux 64 bit. I am aware that the whitespace formatting is slightly off which is an artifact of my cutting and pasting but the code IS EXACTLY as I am running it otherwise.
<pre> <code>
from __future__ import division
import sys
from math import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(tparent)
self.browser = QTextBrowser()
self.lineedit = QLineEdit("Type an epression and press enter")
self.lineedit.selectAll()
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit(self.setFocus()
self.connect(self.lineedit, SIGNAL("returnPressed()"),self.updateUi)
self.setWindowTitle("Calculate")
def updateUI(self):
try:
text = unicode(self.lineedit.text())
self.browser.append("%s = <b>%s</b>" % (text, eval(text)))
except:
self.browser.append("<font color=red>%s is invalid!</font>" % text)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
You're missing a close paren from the line above
self.lineedit(self.setFocus())
self.connect(self.lineedit, SIGNAL("returnPressed()"),self.updateUi)

Categories

Resources