pyqt check if value of lineEdit changed - pyqt

I Need to check if the value of a lineEdit in PyQt4 changed, if this value is changed I Need to Trigger a Slot.
My code:
self.connect(self.ui.lineEdit, QtCore.SIGNAL("textChanged (QString & text"), self.sync_lineEdit)
Nothing happend if I Change the value in the GUI.
Any idea how to fix this Problem?
Kind regards;

Try simple connect:
self.ui.lineEdit.textChanged.connect(self.sync_lineEdit)
...
def sync_lineEdit(self, text):
print text
This should work fine

Related

Reload UI, Rather Than Recreating

import sys
import webbrowser
import hou
from PySide2 import QtCore, QtUiTools, QtWidgets, QtGui
# Calling UI File & Some Modification
class someWidget(QtWidgets.QWidget):
def __init__(self):
super(someWidget,self).__init__()
ui_file = 'C:/Users/XY_Ab/Documents/houdini18.5/Folder_CGI/someUI.ui'
self.ui = QtUiTools.QUiLoader().load(ui_file, parentWidget=self)
self.setParent(hou.qt.mainWindow(), QtCore.Qt.Window)
self.setFixedSize(437, 42)
self.setWindowTitle("Requesting For Help")
window_C = someWidget()
window_C.show()
So, I have created this small script that shows the UI, I have connected this to Houdini Menu Bar. Now The Problem is if I click the menu item multiple times it will create another instance of the same UI & the previous one stays back, What I want is something called "If Window Exist Delete It, Crate New One" sort of thing.
Can someone guide me? I am fairly new to python in Houdini and Qt so a little explanation will be hugely helpful. Also, why can't I use from PySide6 import?? Why do I have to use from PySide2?? Because otherwise Houdini is throwing errors.
For the same thing what used to do in maya is
# Check To See If Window Exists
if cmds.window(winID, exists=True):
cmds.deleteUI(winID)
Trying to do the same thing inside Houdini.
I don't have Maya or Houdini, so I can't help you too much.
According to https://www.sidefx.com/docs/houdini/hom/cb/qt.html
It looks like you can access Houdini's main window. The main reason the window is duplicated or deleted is how python retains the reference to window_C. You might be able to retain the reference to just show the same widget over and over again by accessing the main Houdini window.
In the examples below we are using references a different way. You probably do not need your code that has
self.setParent(hou.qt.mainWindow(), QtCore.Qt.Window)
Create the widget once and keep showing the same widget over and over.
import hou
# Create the widget class
class someWidget(QtWidgets.QWidget):
def __init__(self, parent=None, flags=QtCore.Qt.Window): # Note: added parent as an option
super(someWidget,self).__init__(parent, flags)
...
MAIN_WINDOW = hou.ui.mainQtWindow()
try:
MAIN_WINDOW.window_C.show()
except AttributeError:
# Widget has not been created yet!
# Save the widget reference to an object that will always exist and is accessible
# parent shouldn't really matter, because we are saving the reference to an object
# that will exist the life of the application
MAIN_WINDOW.window_C = someWidget(parent=MAIN_WINDOW)
MAIN_WINDOW.window_C.show()
To delete the previous window and create a new window.
import hou
# Create the widget class
class someWidget(QtWidgets.QWidget):
def __init__(self, parent=None, flags=QtCore.Qt.Window): # Note: added parent as an option
super(someWidget,self).__init__(parent, flags)
...
MAIN_WINDOW = hou.ui.mainQtWindow()
# Hide the previous window
try:
MAIN_WINDOW.window_C.close()
MAIN_WINDOW.window_C.deleteLater() # This is needed if you parent the widget
except AttributeError:
pass
# Create the new Widget and override the previous widget's reference
# Python's garbage collection should automatically delete the previous widget.
# You do not need to have a parent!
# If you do have a parent then deleteLater above is needed!
MAIN_WINDOW.window_C = someWidget() # Note: We do not parent this widget!
MAIN_WINDOW.window_C.show()
Another resource shows you can access the previous widget from the page level variable. https://echopraxia.co.uk/blog/pyqt-in-houdinimaya-basic This is possible, but seems odd to me. The module should only be imported once, so the page level variable "my_window" should never exist. However, it sounds like the Houdini plugin system either reloads the python script or re-runs the import. If that is the case every time you show a new window from the import of the script, you are creating a new window. If the previous window is not closed and deleted properly, Houdini could have an ever growing memory issue.
try:
my_window.close()
except (NameError, Exception):
pass # Normal python would always throw a NameError, because my_window is never defined
my_window = MyWindow()
#This is optional you can resize the window if youd like.
my_window.resize(471,577)
my_window.show()
PySide6
https://www.sidefx.com/docs/houdini/hom/cb/qt.html
The bottom of the page shows how to use PyQt5. The same would apply for PySide6. Houdini just happens to come with PySide2.

searching for tags in Tkinter Text widget

i am using a tkinter Text widget to display the content of gerber-code files.
the program runs on a raspberry pi and send code over serial to a machine one line of text at at time.
i set the current active line as follows:
class TextEditor(tkinter.Text):
def __init__(self, tkRoot):
...
self.tag_configure("activeLine", background="#87e8ed")# set the colour used for activeLine
def setLine(self, lineNumber):
self.tag_remove("activeLine", "1.0", "end")
self.tag_add("activeLine", str(lineNumber)+".0 linestart", str(lineNumber)+".0 lineend+1c")
def getLine(self):
pass # need to return the activeLine line number
there should only ever be one line at a time highlighted with "activeLine" so the first instance would be fine.
i could store a variable in the call to setLine and read it back in getLine but i would prefer not to as any edits to the text it could go out of sink
i notice using IDLE that the debugger uses what looks the same principle as i am trying to achieve here to set breakpoints, is it possible and if so where would i start looking for the IDLE source code to look into how it is achieved there, i am currently writing this on a Ubuntu 18.04 desktop i would like to no best ways to search IDLE source from
any help would be greatly appreciated, i am quite new to python and tkinter as i am generally a windows dot.net programmer but i am now learning to use Linux
i have now found an answer to my own question
listing all the functions of the text widget that start with "tag_" like this:
d = dir(self.tkRoot.text)
for dv in d:
s = str(dv)
if s.startswith("tag_"):
print(dv)
i found the method "tag_ranges(name)" that returns me this
(<textindex object: '5.0'>, <textindex object: '6.0'>)
at the time of calling the current line was 5

Creating variables associated with buttons in tkinter

I'm trying to create a calculator in Tkinter. Although my current code works well to create the buttons with the correct number on each button since the function is only called after the iteration creating the variables is done, x is always 8, and thus all buttons have a value of 8. How could I circumvent this problem?
I tried without using lambda to call the function, but then the buttons don't even work at all, I'm not really sure why.
Heres the basic code:
from tkinter import *
window=Tk()
ButtonFrame=Frame(window)
ButtonFrame.place(x=100,y=100)
def NumPressed (Digit):
print(Digit)
for y in range(3):
for x in range(3):
NumTXT=y*3+x
Buttonx=Button(ButtonFrame,text=NumTXT,command=lambda:NumPressed(NumTXT))
Buttonx.grid(row=y,column=x)
It has to do with default values in the lambda function. After the buttons are all created the NumTXT variable == 8. Each time you press a button it uses the current value of NumTXT.
You can fix this by giving the lambda function a default value which doesn't change:
command=lambda x=NumTXT: NumPressed(x)
^
# Set default value
then each button will have a lambda function with a default value as NumTXT was at button creation.

Stuck in infinite loop after destroying parent window (python, Tkinter)

The problem I am encountering is that I appear to be stuck in an infinite loop, (If I am not, please correct me). I am using tkinter for python 3.6 (64 bit) on windows 10.
In the module I am having an issue with I have 3 entry widgets and 2 buttons. Both buttons call the "destroy()" function in order to kill the parent window.
Below is a heavily abstracted version of my module, the purpose of the module is to take inputs from the entry widget and write them to a file.
def Create():
parent = Tk()
parent.MakeItlookNice
entry1 = Entry(parent)
entry1.insert(INSERT, "Please enter your desired username here")
entry2 = Entry(parent)
entry2.insert(INSERT, "Please enter your desired password here")
entry3 = Entry(parent)
entry3.insert(INSERT, "What is your mother's maiden name")
Submit = tk.Button(parent,
text ="Click here to submit your stuff",
command = lambda: [parent.destroy(),
submit.function()])
Cancel = tk.Button(parent,
text ="Click here to cancel your request",
command = lambda: parent.destroy())
parent.mainloop()
This function is contained within the module "RegisterNewUser". The "Menu" module is the module that called this function. As far as I am aware once parent.destroy() is called there is no more code to execute since it is all contained within parent.mainloop(), therefore the function is finished and the "Menu" module should continue executing.
What should happen:
I want the Submit button to destroy the window, execute the function and then return to the "Menu" module.
I want the cancel button to destroy the window and return to the "Menu" module.
What actually happens:
The window closes, like it is supposed to
But the code inside the "Menu" module does not start executing again
When I go to close the python shell, it warns me that the program is still running
Ultimately my question is, what code is still running and why hasn't it stopped?
Thank you for reading this and if you require more detail please let me know.
EDIT: I have done research on this topic before posting this question. I have read the documentation on both the tk.destroy() function and the tk.mainloop() function, I have also opened up the Tkinter module in IDLE to try and understand what happens at a deeper level but after all this, I was still unable to figure out a solution. This is my first question on stack overflow, please forgive me if I have done anything wrong.
Hmmm, so you say multiple windows? an easier way to achieve a complex UI as such is using a concept called frames. Tkinter allows you to completely change you screen and layout if you switch to a new frames. This might require you to reprogram alot of code. for an example see Switch between two frames in tkinter
Also, Some guy built a really nice Bitcoin monitoring app using tkinter and frames on youtube
I think you would probably benefit from using Toplevel() here.
I have taken the code you provided and added it to a class used to create the main window and to manage the pop up window.
I noticed a few things with you code.
Its obvoious you are importing tkinter twice like this:
import tkinter as tk
from tkinter import *
I can tell from how you have written your entry fields vs your buttons. Do not do this. Instead just used one or the other. I recommend just using import tkinter as tk.
You are using a function to create a new tkinter instance and judging by your question you all ready have a tkinter instance created for your menu. Instead of creating new Tk() instances you can use Toplevel() instead to open a new window that can inherit everything from the main window and should be easier to manage.
You do not really need to use lambda in this situation. I have also removed the lambda function and replaced with a simple command that will work here.
Take a look at the below code and let me know if you have any questions.
import tkinter as tk
class MyApp(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)
self.master = master
self.master.title("Main MENU")
tk.Button(self.master, text="Open top level", command = self.create).pack()
def create(self):
self.top = tk.Toplevel(self.master)
entry1 = tk.Entry(self.top, width = 35)
entry1.pack()
entry1.insert(0, "Please enter your desired username here")
entry2 = tk.Entry(self.top, width = 35)
entry2.pack()
entry2.insert(0, "Please enter your desired password here")
entry3 = tk.Entry(self.top, width = 35)
entry3.pack()
entry3.insert(0, "What is your mother's maiden name")
tk.Button(self.top, text ="Click here to submit your stuff",
command = self.Submit).pack()
tk.Button(self.top, text ="Click here to cancel your request",
command = self.top.destroy).pack()
def Submit(self):
print("Do something here to submit data")
self.top.destroy()
if __name__ == "__main__":
root = tk.Tk()
app1 = MyApp(root)
tk.mainloop()
You can use toplevel() and its library function wait_window() just prior to (or instead of) your mainloop() and your problem will be solved
wait_window() mentioned above worked for me in the code below replacing popup.mainloop() with it, the mainloop() kept my code in an infinite loop upon the popup even after okay button was hit

Can a tkinter button return a value from an entry on-click?

I'm doing an extended project as one of my qualifications in my current College and I chose to write a python Strategy/RPG game. As a result, I ended up with the highest level of Python knowledge (Surpassing my Computing Teacher who only ever uses the basics... and used Tkinter only once a few years ago. Every one else who has decided to make a program, are either coding in Lua, Java, C++, HTML/CSS/Java-Script or, those who are coding in python, they are only using the basics learned from our teacher.)
I say "Highest level of Python knowledge" but really it isn't that high... I only know a little beyond the basics.
As a result, a forum post is the best place I can turn to for help.
So in my game I defined this function:
#"Given_String" is the question that one would want to ask. (With the answer being an integer between 1 and "Choice_Range" (inclusive)
def Value_Error(Given_String,Error_Message,Choice_Range):
while True:
try:
Temp=int(input(Given_String))
if Temp<1 or Temp>Choice_Range:
print(Error_Message)
else:
break
except ValueError:
print(Error_Message)
return Temp
I then wanted to add tkinter to my code, because the game would have to be in a separate window, and not in the console. As a result, I had to change this code so that it displays the "Given_Message" and the "Error_Message" in a tkinter window, and uses the value that has been typed into an entry box when defining "Temp".
I wrote this code to make this work: (Or at least most of it)
#This code is stored in a different file for neatness and hence I had to import "sys" to avoid circular imports.
#This code is made to be flexible so that I can later re-use it when necessary.
#This code starts with the function all the way at the bottom. The rest are made to add flexibility and to structure the algorithm.
#This code hasn't been fully run (Because of the Error crashing the Python Shell) so it can contain other Run-time Errors that I'm not aware of yet.
import sys
def Generate_Window(Window_Name,X_Parameter=5,Y_Parameter=50):
Temp=sys.modules['tkinter'].Tk()
Temp.title(Window_Name)
Temp.geometry(str(X_Parameter)+"x"+str(Y_Parameter))
return Temp
def Generate_Button(Master,Text="Submit"):
Temp=sys.modules["tkinter"].Button(Master,text=Text)
return Temp
def Generate_Entry(Master):
Temp=sys.modules["tkinter"].Entry(Master)
return Temp
def Generate_Label(Master,Given_String):
Temp=sys.modules["tkinter"].Label(Master,text=Given_String)
return Temp
def Com_Get_Entry(Given_Window,Given_Entry):
Temp=Given_Entry.get()
Given_Window.destroy()
return Temp
def Com_Confirm(Given_Window):
Given_Window.destroy()
def Generate_Entry_Box(Given_String):
Entry_Window=Generate_Window("Entry",X_Parameter=300)
Entry_Label=Generate_Label(Entry_Window,Given_String)
Entry_Entry=Generate_Entry(Entry_Window)
Entry_Button=Generate_Button(Entry_Window)
Entry_Button.configure(command=lambda:Com_Get_Entry(Entry_Window,Entry_Entry))
Entry_Label.grid(row=0,columnspan=2)
Entry_Entry.grid(row=1,column=0)
Entry_Button.grid(row=1,column=1)
def Generate_Alert_Message(Given_String):
Alert_Window=Generate_Window("Alert",X_Parameter=300)
Alert_Label=Generate_Label(Alert_Window,Given_String)
Alert_Button=Generate_Button(Alert_Window,Text="OK")
Alert_Button.configure(command=lambda:Com_Confirm(Alert_Window))
Alert_Label.grid(row=0,columnspan=2)
Alert_Button.grid(row=1,column=1)
def Get_Interger_Input_In_Range(Given_String,Error_Message,Choice_Range):
while True:
try:
Returned_Value=int(Generate_Entry_Box(Given_String))
if Returned_Value<1 or Returned_Value>Choice_Range:
Generate_Alert_Message(Error_Message)
else:
break
except ValueError:
Generate_Alert_Message(Error_Message)
return Temp
I already included in my code all that I was struggling with and that I could find an answer to.
I.E: On-click, do a certain action with given parameters.
One thing I could not find, is how to return the entered value to the original (Get_Interger_Input_In_Range()) function after the button has been clicked.
What I mean is something like this:
def Function1(GivenParameter1,GivenParameter2):
Temp=Function2(GivenParameter1)
Temp+=GiverParameter2 #random action
return Temp
def Function2(GivenParameter):
Button=Button(Master,command=Function3).grid()
Entry=Entry(Master).grid()
def Function3():
Temp=Entry.get()
return Temp
In Function1 I want Temp to equal the entered value from Function2.
Is there any way to do this without using classes? (I'm not too familiar with classes yet)
Is there any way to do this at all?
I haven't seen anyone give the answer I was looking for...
Because even if they said to use classes... I still didn't know how to return it (Explanation just below)
#The following code was written quickly for purposes of explaining what I mean. It doesn't actually work... (It seems that the button command is being called automatically...)
from tkinter import *
class Return_Value_In_Entry():
def __init__(self):
self.Master=Tk()
self.Entry=Entry(self.Master)
self.Button=Button(self.Master,text="Submit",command=self.Return())
def Return(self):
self.TempVar=self.Entry.get()
return self.TempVar
The way I see it, the Return() function would return the value to the button and not the function/assignment that called the class ... Which is the same problem I'm having with my code.
If you read this all then I really appreciate it. I hope someone can answer my question and tell me (if it's impossible otherwise) how to use classes to solve my "Little" yet large problem.
I fixed your example code (I think). The main problem is that this:
command=self.Return()
does not do what you think it does. It just assigns return value from Return() to command. This is incorrect. It should be
command=self.Return
This assigns function Return to command. Subsequently, when ever button is pressed, self.Return() is executed.
The full example is here:
from tkinter import *
class Return_Value_In_Entry():
def __init__(self):
self.Master=Tk()
self.Entry=Entry(self.Master)
self.Entry.pack()
self.Button=Button(self.Master,text="Submit",command=self.Return)
self.Button.pack()
self.Master.mainloop()
def Return(self):
self.TempVar=self.Entry.get()
print(self.TempVar)
Return_Value_In_Entry()
Now, whenever you press the Button, the value from the Entry widget is saved into self.TempVar and printed out, just to check if its working. Hope this helps.
Gif showing how the example program works:

Resources