I have created a simple test program in Qt Designer that allows you to select a folder and display its contents on a window. It looks like this:
I have successfully converted the .ui file to .py without fail. Next, here is my code to run the program, aptly named main.py:
from PyQt4 import QtGui
import sys
import design
import os
class ExampleApp(QtGui.QMainWindow, design.Ui_MainWindow):
def _init_(self):
super(self._class_, self)._init_()
self.setupUI(self)
self.btnBrowse.clicked.connect(self.browse_folder)
def browse_folder(self):
self.listWidget.clear()
directory = QtGui.QFileDialog.getExistingDirectory(self,"Pick a Folder")
if directory:
for file_name in os.listdir(directory):
self.listWidget.addItem(file_name)
def main():
app = QtGui.QApplication(sys.argv)
form = ExampleApp()
form.show()
app.exec_()
if __name__ == '__main__':
main()
In my command prompt, I run the following code:
python main.py
It proceeds to load for a second or two, and then I get this:
Is there something that I am doing wrong? Why isn't my program showing up the way it should be? Any help is appreciated!
These lines are wrong:
def _init_(self):
super(self._class_, self)._init_()
Instead you want something like:
def __init__(self, parent=None):
super(ExampleApp, self).__init__(parent)
Note the double underscores, the different super argument, and passing parent to the super class. I can't test this right now, but it should be much closer to working.
By naming your __init__ method incorrectly it never would've been called. That explains why you get a window but not the one you designed.
Related
I'm using PyQt to build a simple IDE and getting weird errors if you load an empty file. A small example script is posted below:
#!/usr/bin/env python
import sys
from PyQt4 import QtGui
class TestApp(QtGui.QMainWindow):
def __init__(self, filename=None):
super(TestApp, self).__init__()
self._editor = QtGui.QPlainTextEdit()
self._editor.modificationChanged.connect(self._change_modified)
self.setCentralWidget(self._editor)
self._editor.setPlainText('a')
def _change_modified(self, have_change):
print(have_change)
if __name__ == '__main__':
a = QtGui.QApplication([])
app = TestApp()
app.show()
sys.exit(a.exec_())
As expected, this shows a window with a plain text editor. As soon as the setPlainText method is called, the editor emits two events: One modificationChanged event with changes=True, a second with changes=False.
A bit weird, but fine.
However, if you change setPlainText('a') to setPlainText(''), only a single event is emitted, this time with changes=True. Even worse, after telling the editor it's not modified with setModified(False), it insists it's been changed somehow.
Does anyone know what's causing this and how I can work around this issue?
Update: It seems to be a bug & also affects QPlainTextEdit.clear().
The workaround below places a wrapper around the QPlainTextEdit to fix clear() and setPlainText('').
#!/usr/bin/env python
import sys
from PyQt4 import QtGui
class TestApp(QtGui.QMainWindow):
def __init__(self, filename=None):
super(TestApp, self).__init__()
self._editor = PlainTextEdit()
self._editor.modificationChanged.connect(self._change_modified)
self.setCentralWidget(self._editor)
self._editor.setPlainText('')
def _change_modified(self, have_change):
print(have_change)
class PlainTextEdit(QtGui.QPlainTextEdit):
def clear(self):
self.selectAll()
cursor = self.textCursor()
cursor.removeSelectedText()
doc = self.document()
doc.clearUndoRedoStacks()
doc.setModified(False)
self.modificationChanged.emit(False)
def setPlainText(self, text):
if text:
super(PlainTextEdit, self).setPlainText(text)
else:
self.clear()
if __name__ == '__main__':
a = QtGui.QApplication([])
app = TestApp()
app.show()
sys.exit(a.exec_())
It's a Qt bug, and the straightforward workaround is to check for empty contents if modifications are indicated.
I am trying to make a pretty big app with many different parts and windows. I decided that it would look a lot cleaner if I had some windows have their own file and then import them into the main file. I tried to do this but when I try to run the class, it gives the error of needing three arguments. I do not understand how I should go about doing this so any help will be greatly appreciated!
Main file:
import wx
import Login
Login.apples(self,parent,id)
class oranges(wx.Frame):
def __init__(self,parent, id):
wx.Frame.__init__(self,parent,id,"Mail",size=(700,700))
self.frame=wx.Panel(self)
if __name__=="__main__":
app=wx.App(False)
window=oranges(parent=None, id=-1)
window.Show()
app.MainLoop()
I get a NameError: name "self" is not defined.
import wx
class apples(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,"Login to Mail",size=(400,400))
self.frame=wx.Frame(self)
if __name__=="__main__":
app=wx.App(False)
window=apples(parent=None, id=-1)
window.Show()
app.MainLoop()
import wx
import Login
#Login.apples(self,parent,id) #this line wont work ... there is no self here...
#see below in the if __name__ == "__main__" part
class oranges(wx.Frame):
def __init__(self,parent, id):
wx.Frame.__init__(self,parent,id,"Mail",size=(700,700))
self.frame=wx.Panel(self)
if __name__=="__main__":
app=wx.App(False)
window=oranges(parent=None, id=-1)
other_window = Login.apples(parent=None,id=-1)
window.Show()
other_window.Show()
app.MainLoop()
The error is that you included self as an argument in your call to Login.apples(). The first argument in a class method (usually called self) should not be included in function calls (only function definitions), and is treated implicitly in Python. It is used to handle references within the class methods to the class itself (or other class attributes/functions). See this post for information on self
However, once you fix this, your code will still not run with the same error because you given no value to parent or id. You will need to provide values for these variables before asking python to call a function with them
I have a program with two windows, main and the settings.
When I run setText on a QLineEdit in the settings.py file, the new string is not in the GUI, and I can see the string before the setText code.
When I put the same code in the settingsUI file generated from Qt Designer, It works. But in the settings.py doesn't.
The settings file is the file that contains the SettingsWindow class and I can put the real python code in it.
The settingsUI file is the file that contains the GUI, I generated it with pyuic4 (or pyuic5).
This code works in settingsUI file:
self.browse_file.setText("safa")
But dosen't work in settings file.
--UPDATE--
import sys
from PyQt4 import QtCore, QtGui
from settingsui import Ui_Dialog
class SettingsWindow(QtGui.QDialog, Ui_Dialog):
def __init__(self):
QtGui.QDialog.__init__(self)
Ui_Dialog.__init__(self)
self.setupUi(self)
self.lineEdit.setText("safa")
print self.lineEdit.text()
After: self.lineEdit.setText("safa") , I can't see any text in the QLineEdit.
print self.lineEdit.text() outputs the text "safa"
The problem is in your mainwind.py file.
You try to use the following method for opening the dialog:
def buttonclicked(self):
Dialog = QtGui.QDialog()
u = settings.SettingsWindow()
u.setupUi(Dialog)
Dialog.exec_()
The reason why the text doesn't show, is because you are creating two dialogs. The second one (named u) has setText() called on it, but then gets thrown away without being shown.
Your method should instead look like this:
def buttonclicked(self):
dialog = settings.SettingsWindow()
dialog.exec_()
All the setup code for the SettingsWindow dialog is already inside its __init__ method, so all you need to do is create an instance of it.
PS:
In MainWindow.__init__ you have Ui_MainWindow.__init__(self), and in SettingsWindow.__init__ you have Ui_Dialog.__init__(self). These lines don't do anything useful, because the Ui_* classes are just simple subclasses of object. So those two lines could be removed.
Shouldn't you initialize your UI along these lines:
class SettingsWindow(QtGui.QDialog):
def __init__(self, parent = None):
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.lineEdit.setText("safa")
print self.ui.lineEdit.text()
This is how I do it all the time and works like a charm.
I have created gui form using qtdesigner and converted in to python code using pyuic4. Sample of my main script is as follows:
#!/usr/bin/env python
from PyQt4 import QtGui
from multibootusb_ui import Ui_Dialog
import sys
import os
import another_file_function
class AppGui(QtGui.QDialog,Ui_Dialog):
def __init__(self):
QtGui.QDialog.__init__(self)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.close.clicked.connect(self.close)
another_file_function.function2()
def function1():
self.ui.text_label.setText("some text")
function1()
app = QtGui.QApplication(sys.argv)
window = AppGui()
ui = Ui_Dialog()
window.show()
sys.exit(app.exec_())
To make it easy i have created different function in different file. So that it can be accessed at any time by any scrips.
Here is the sample of function from another_file_function:
#!/usr/bin/env python
def function2():
#code here
self.ui.text_label.setText("some text")
The function1 from main script and function2 from another_file_function are same. Also I am calling function2 from main class. The problem is that when i use function1() from main script it updates the GUI text without an issue. However, if i use the same function in different file and call that function from main script it fails to update and i get global name 'self' is not defined error.
Where am I getting wrong? Any help is appriciated.
Thank you.
I am unclear why function1 works either, I am going to assume it has a self in it's definition that you dropped.
To get function2 to work you need to do something like:
other file:
def function2(input):
#code here
input.ui.text_label.setText("some text")
main file:
#!/usr/bin/env python
from PyQt4 import QtGui
from multibootusb_ui import Ui_Dialog
import sys
import os
import another_file_function
class AppGui(QtGui.QDialog,Ui_Dialog):
def __init__(self):
QtGui.QDialog.__init__(self)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.close.clicked.connect(self.close)
another_file_function.function2()
def function1(self):
self.ui.text_label.setText("some text")
function1()
app = QtGui.QApplication(sys.argv)
window = AppGui()
another_file_function.function2(window)
window.function1()
window.show()
sys.exit(app.exec_())
I am learning PyQt and coming from webdesign, so excuse this question that must have very obvious answer.So I am building a PyQt application and I would like to spread methods to several files to correspond different parts of GUI. How can I access textbox locating in fileA.py from fileB.py. :
#fileA.py
import sys
from PyQt4 import QtGui, QtCore
from gui1 import Ui_MainWindow
import fileB
class MyApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
#This works all fine
def pressed():
window.plainTextEdit.appendPlainText("Hello")
window.pushButton.pressed.connect(pressed)
window.button2.pressed.connect(fileB.func3)
sys.exit(app.exec_())
Now, in this file I would like to use textbox from fileA.py
#fileB.py
import fileA
#How do I access window.plainTextEdit from fileA.py
def func3():
print "hello"
fileA.window.plainTextEdit.appendPlainText("Hello")
What am I doing wrong? What would be best way to spread functionality to multiple files if not this?
Thank you for taking time to read this.
You can take advantage of Python's class inheritance, like so:
fileA.py:
import sys
from PyQt4 import QtGui, QtCore
from gui1 import Ui_MainWindow
import fileB
class MyApp(fileB.MyApp, QtGui.QMainWindow):
def __init__(self):
self.MyMethod()
# Should print 'foo'
fileB.py:
import sys
from PyQt4 import QtGui, QtCore
from gui1 import Ui_MainWindow
class MyApp(QtGui.QMainWindow):
def MyMethod(self):
print 'foo'
Well, first off, the code under if __name__ == "__main__" will never be run when you are importing fileA.py, and so fileA.window does not exist. That's what it should do: run only when __name__ is "__main__", i.e. run as a top-level program. Instead, you should import fileA.py, create the QApplication and window again, then access window.plainTextEdit. However, this creates a very tight coupling between the code, as you are directly accessing a widget in MyApp from fileB. It might be better if instead, you expose a method in MyApp that appends to the text box instead of having fileB.py do it directly. So you may want to think about what you want to do and how to structure your program.
Of course, you don't have to structure your code that way; you could simply do
window = MyApp()
window.plainTextEdit.appendPlainText("Hello")
in fileB if you wanted.