Store string variables from PyQt4 Text Box - python

I have created a small uic file with qt Designer in order to build a small gui using PyQt4. One of the elements of that gui is a simple textbox, where I set a string value (textbox is called RiskDate_Box). After setting this value in the GUI, I want to use it as a string variable in the following code (not seen here) . My problem is, that I am not able to store it, in the code seen below I tried it in two different ways ( store it as Riskdate1 and Riskdate2). After compiling the code, bothvariables are empty and not equal to the value I set in the GUI, e.g. '12.08.2012'. However, if I compile the script and after that only compile
Riskdate2=window.RiskDate_Box.toPlainText()
then the Riskdate set in the Gui is correctly assigned to the variable 'Riskdate2' as a string. Would be great if someone could help me with that issue.
from PyQt4 import QtCore, QtGui, uic
import sys
# Gui Code
qtCreatorFile = "untitled.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class MyWindow(QtGui.QDialog):
def __init__(self):
super(MyWindow, self).__init__()
uic.loadUi("untitled.ui", self)
self.show()
self.RiskDate=self.RiskDate_Box.toPlainText()
if __name__ == '__main__':
app=QtGui.QApplication.instance()
app=0
app = QtGui.QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)
window = MyWindow()
#Try 1 to store variable
Riskdate1=window.RiskDate
# Try 2 to store variable
Riskdate2=window.RiskDate_Box.toPlainText()
sys.exit(app.exec_())

you need to send s signal when text in your QPlainTextEdit is changed
void QPlainTextEdit::textChanged()
This signal is emitted whenever the document's content changes; for example, when text is inserted or deleted, or when formatting is applied.
you need to do something like:
self.RiskDate_Box.textChanged.connect(self.get_text)
self.show()
def get_text(self):
self.RiskDate = self.RiskDate_Box.toPlainText())
print (self.RiskDate)

Related

How to reference & change a PyQt5 window object from another window class or from an extra .py file such as init_events_ui.py

Is it possible to add another .py file (via import) and use it as an initialisation and event handler for a PyQt5 Multiwindow project other window & main .py files?
I have a project that consists of the following files:
main.py - the main app which imports the Ui...py files below & the ui_init_events.py file also
main.py - the main program
Ui_main_window_ui.py - a complied Qt UI to display the main window
Ui_frmConsoleLog_ui.py - a complied Qt UI to display a window with a textEdit & comboBox objects
ui_init_events.py - I want this file to have functions for setting each windows Ui object fields as well as contain the Ui windows object events such as btn.clicked.connect(self.SomeotherFunc)
I have found both these posts helpful but am stuck as I do not know how to reference objects other than the self object and can't find where this is explained. See: PyQt: Modifying Widget Object from another Function
Multiple Windows in PyQt4
In the 2nd post they are using multi-windows (via the QDialog) object also, however they are only using a single .py file. I am using Visual Studio Code & have built the Ui files then complied them. They are works in progress so I expect to make more changes meaning they wil be overwritten so I do not want to edit these files.
I cannot work out how to reference and change the properties in another window for initialisation purposes. The thread is:
Here is the main bits. Currently I call a function to return some data using self.combobox.additems (see #1) but I think calling this over and over again from main.py somewhat decreases code readability.
(#2) Therefore I would like advice how to move all the initialisation parts of an existing PyQt window (being an imported .py file used to generate the window + controls) into a separate .py file (eg named ui_init_events.py).
However in trying & researching this I do not know nor can find an example how to reference the objects using their full hierarchical naming convention. I have tried Application. QWindow., etc. I only know how to use self.... and it isn't working (of course as that would be the referring to the function itself I understand that its being called in, not the PyQt window I'm wanting to reference). See (#3) for what is not working.
Any ideas please on resources available to assist with understanding how PyQt labels its objects from the root of the object tree is appreciated as well as an example of how to set the comboBox_Selector in the Ui_frmConsoleLog window from app.py or another .py file other than from the Ui_frmConsoleLog_ui.py or within the class definition under --init--(self, parent=None): ?
The desired file structure is like this:
+-- main.py (or app.py)
|
+--- Ui_main_window_ui.py (has setupui & adds objects for main window)
|
+--- Ui_main_window_init.py (has init code for Ui_main_window_ui.py)
|
+--- Ui_main_window_events.py (has event code for Ui_main_window_ui.py)
|
+--- Ui_frmConsoleLog_ui.py (has setupui & adds objects for 2nd window)
|
+--- Ui_frmConsoleLog_init.py (has init code for Ui_frmConsoleLog_ui.py)
|
+--- Ui_frmConsoleLog_events.py (has event code for Ui_frmConsoleLog_ui.py)
main.py file contents
# Default imports
import sys, os, io, sched, time
import ui_resources_rc
from PyQt5.QtCore import QObject, QThread, pyqtSignal
from configparser import ConfigParser
...a portion of code here uses a ini config file for retrieving/saving some settings of the UI & I want to set the properties for each object accordingly...
from PyQt5.QtWidgets import (QApplication, QDialog, QMainWindow, QMessageBox, QWidget)
from PyQt5.uic import loadUi
from Ui_main_window_ui import Ui_MainWindow
from Ui_frmConsoleLog_ui import Ui_frmConsoleLog
from ui_init_events import (funcUpdateFormCombos)
...todo... open a network connection to the system (its an inverter)
# This window will be used for filtering network poll event types
class ConsoleLogWindow(QWidget, Ui_frmConsoleLog):
def __init__(self):
super().__init__()
self.setWindowTitle('Console Log')
class AppWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.win = None # No Console Log window visible yet.
self.setupUi(self)
#(1) Here is where I will have to call this a lot of times to
# populate the vaious window objects which I dont want to do
self.comboBox_Selector.addItems(funcUpdateFormCombos())
self.action_Console.triggered.connect(self.OpenConsoleLogWindow)
self.action_About.triggered.connect(self.about)
# Populate the controls as per the config file
#initialise() <-- (2) Here is where I want to call a
# function in ui_init_events.py to setup
# the form's objects as created in QtDesigner
# & exported as a .py file. I want to continue
# to edit each PyQt window later so I dont want
# to add to the Ui_... files themselves but in
# main.py call a function that has the code to
# set the object fields like checked, combobox
# list contents, etc.
def OpenConsoleLogWindow(self, checked):
if self.win is None:
self.win = ConsoleLogWindow()
self.win.show()
else:
self.win.close() # Close window.
self.win = None # Discard reference.
if __name__ == "__main__":
app = QApplication(sys.argv)
win = AppWindow()
win.show()
print('HERE')
sys.exit(app.exec())
ui_init_events.py file contents (this is the file I want to house all window object setup without editing the PyQt UI converted .ui to .py files such as Ui_main_window_u.py & Ui_frmConsoleLog_ui.py which I don't want to edit at all.
# Contains the initialisation of widgets fields
def funcUpdateFormCombos():
LIST = ['Amps', 'Volts', 'Watts']
LIST.sort()
return tuple(LIST)
# Would prefer to have a single file per Ui_...py file that houses
# all the events that get triggered for each Ui windows.
# How is this done? eg: <not working> (3)
def initialise()
frmConsoleLog.self.comboBox_Selector.addItems('Watts','Amps','Volts')
Contents of Ui_frmConsoleLog_ui.py (has the combobox I want to populate)
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_frmConsoleLog(object):
def setupUi(self, frmConsoleLog):
frmConsoleLog.setObjectName("frmConsoleLog")
frmConsoleLog.resize(640, 468)
frmConsoleLog.setToolTip("")
frmConsoleLog.setStatusTip("")
frmConsoleLog.setAccessibleName("")
self.horizontalLayout = QtWidgets.QHBoxLayout(frmConsoleLog)
self.horizontalLayout.setContentsMargins(0, 1, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.comboBox_Selector = QtWidgets.QComboBox(frmConsoleLog)
self.comboBox_Selector.setObjectName("comboBox_Selector")
self.horizontalLayout.addWidget(self.comboBox_Selector)
self.textEdit_ConsoleLog = QtWidgets.QTextEdit(frmConsoleLog)
self.textEdit_ConsoleLog.setEnabled(True)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.textEdit_ConsoleLog.sizePolicy().hasHeightForWidth())
self.textEdit_ConsoleLog.setSizePolicy(sizePolicy)
self.textEdit_ConsoleLog.setObjectName("textEdit_ConsoleLog")
self.horizontalLayout.addWidget(self.textEdit_ConsoleLog)
self.retranslateUi(frmConsoleLog)
QtCore.QMetaObject.connectSlotsByName(frmConsoleLog)
def retranslateUi(self, frmConsoleLog):
_translate = QtCore.QCoreApplication.translate
frmConsoleLog.setWindowTitle(_translate("frmConsoleLog", "Console Log"))
Worked it out, thanks to an answer in my previous post (that the poster removed?), here's the snippet that works and allows your functions in another .py file to set MainWindow pyQt object control properties in the parent main.py file for a much tidier project. I honestly don't care that professional devs think that is not good practice (if they do they are very closed minded).
In app.py (or main.py - I had two files and was playing with names)
class AppWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.win = None # No Console Log window visible yet.
self.setupUi(self)
from init_Ui_main_window import (initMainWindow)
initMainWindow(self)
...
In init_Ui_main_window.py:
def initMainWindow(window):
funcLoadConfig()
# Populate the controls in the main window
window.line_Settings_Simple_Default_Selection.setText(str(SETTINGS_SIMPLE_DEFAULT_SELECTOR))
Note: SETTINGS_SIMPLE_DEFAULT_SELECTOR is a globally defined static variable that wont ever be changed as its read from a config ini file. The user will be able to change the line value if they want to override the default, but it's nice to have a default value populated.
Was that easy as when initMainWindow(self) is called self from the previous object context is passed across to the function and set in function variable window, so to reference the main windows objects its just a case of referencing window.[object name as one would in main.py]

Adding items to QComboBox

I'm trying to add items to two combo boxes.
The code below runs with no errors, I see the list I'm trying to add and "fin" is printed to the terminal, but the combo boxes are showing up empty.
from PyQt5.QtWidgets import QMainWindow
from PyQt5 import QtWidgets
# import GUI from designer file
from main_menu import Ui_main_menu
# import other functions
from add_functions import ChangeLists
class Main(QMainWindow, Ui_main_menu):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.setupUi(self)
self.init_lists()
def init_lists(self):
# Team List
team_list_file = open(r'C:\NHLdb_pyqt\files\NHLteams.txt', 'r')
team_list = team_list_file.read().splitlines()
team_list_file.close()
print("team list: ", team_list)
# Initial Player List
player_list_init = "Please Select a Team"
# Populate combo box lists
self.team_select_combobox.addItems(team_list)
self.player_select_combobox.addItem(player_list_init)
# connect combo box to function that will change player list based on team list selection
# self.team_select_combobox.currentTextChanged.connect(ChangeLists.team_changed)
print("fin")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
main_menu = QtWidgets.QDialog()
ui = Main()
ui.setupUi(main_menu)
# main_menu = Main()
main_menu.show()
sys.exit(app.exec_())
You're using two methods of loading the ui at the same time, the multiple inheritance approach and the "direct approach", and you're actually showing the main_menu instance of QDialog (which doesn't have any init_lists function).
The result is that even if the init_lists is called, it's "shown" (actually, not) in the wrong window, since you're showing the main_menu instance.
Clearly, you should not use both of them, as the first is enough (and usually the most used/suggested), and then show the correct instance object:
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
main_menu = Main()
main_menu.show()
sys.exit(app.exec_())
Do note that there's something else that is wrong with your implementation: you're inheriting from QMainWindow in the Main class, but later you're trying to set up the ui using a QDialog.
Only the base class created in Designer should be used (it doesn't matter what approach you use to load the ui). I can assume that the ui was created using a QDialog (otherwise an exception would have occurred, as a QMainWindow ui would try to use setCentralWidget() which is a function that doesn't exist for QDialog).
So, you either create a new main window in Designer and copy your existing layout in that (if you need the features of a QMainWindow, such as a menu bar, a status bar, dock widgets or toolbars), or you correctly use the QDialog class in the constructor:
class Main(QDialog, Ui_main_menu):
# ...

Detect Ctrl+S ion QTextedit?

So, I'm making a QTextEdit that edits a text file. I got the loading and saving working fine with buttons. But I got the habit of pressing Ctrl+S to save every time I paste something into the textedit because I used that in Notepad before. So I've been trying to implement it. But I can't wrap my head around how to detect and execute my save function. Lets call it savetext.
I've been going around trying to get keyPressEvent to work, but I just don't understand how it works. So I've been pretty helpless in trying to learn it.
My heavily simplified code looks like this:
class GUI(QProcess):
def init etc...
"Button creations and connect to save/load function"
self.textedit=QTextEdit()
def savetext(self):
code
def loadtext(self):
code
Now, how do I detect a key combination being detected in the QTextEdit, or anywhere in my program for that matter, and cause it to do savetext? In my case, Ctrl+S, though I'd just love a general explanation so I could apply it to any combo.
Use QShortcut and QKeySequence
from PyQt5.QtWidgets import QApplication, QTextEdit, QShortcut
from PyQt5.QtGui import QKeySequence
import sys
def slot():
print("Ctrl+S")
app = QApplication(sys.argv)
textedit=QTextEdit()
shortcut = QShortcut(QKeySequence("Ctrl+S"), textedit)
shortcut.activated.connect(slot)
textedit.show()
sys.exit(app.exec_())
You can probably use QShortcut, and right now it will activate only when textedit in focus. If you want to change the behavior please take a look here
Here is a example
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.edit = QtGui.QTextEdit()
layout.addWidget(self.edit)
self.button = QtGui.QPushButton('Test')
layout.addWidget(self.button)
foo = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+S"), self.edit, self.saveCall, context=QtCore.Qt.WidgetShortcut)
def saveCall(self):
self.edit.append('Please save me')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

Set text of textbox on button click

I have the code of a cipher and designed a GUI for it in PyQt and am now attempting to integrate the two now but I have become stuck.
I want to be able to push the Generate Key button which will then run the generatekey function I have and display it in the text box to the left of the button. I tried with .setText() but could not get it to work. The object name for the text box is keytext. Not really sure what to do, when I push the button now it just crashes.
from PyQt5 import QtCore, QtGui, QtWidgets
import sys, random
import cipher ## Designed GUI
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
class CipherDesign(QtWidgets.QMainWindow, cipher.Ui_MainWindow):
def __init__(self, parent=None):
super(CipherDesign, self).__init__(parent)
self.setupUi(self)
self.BGenerate.clicked.connect(self.generatekey) # Generate Button
def generatekey():
key = list(LETTERS)
random.shuffle(key)
return ''.join(key)
def main():
app = QtWidgets.QApplication(sys.argv)
form = CipherDesign()
form.show()
app.exec_()
if __name__ == "__main__":
main()
Your problem is that your generateKey method is missing the self argument and then inappropriately returning the key value rather than assigning it with setText.
In normal Python omitting the self parameter would just give a "number of arguments" error when you call self.generateKey(). But here it is being called by PyQT which is (somewhat unexpectedly) causing a crash.
In Python, a call to a method on an object (like self.generateKey()) is translated into a call like this generateKey(self). self here is just an arbitrary name (self is used by convention). This is the mechanism by which the method is associated to the object on which it is called. Then, in the body of the method, the name self is in scope and is bound to the object instance, as you need it to be to use it in Python.
So you should have something like:
def generatekey(self):
key = list(LETTERS)
random.shuffle(key)
self.TextBoxObject.setText(''.join(key))

QLineEdit is not updating with setText

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.

Categories

Resources