I have a problem that I've partially solved: I want to have a grid layout where I wanna place a certain number of buttons, and let's call that number "x". It's not a difficult task, I can just use a for loop, for example
class Window(Gridlayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for i in range(x):
self.add_widget(Button())
and this works fine, but here comes the first obstacle: I want to have multiple windows and thus the ability to navigate throught them, so I cannot say
class Window(GridLayout)
but I must write
class Window(Screen)
if I want to use the Screen Manager that comes with kivy. To come around this i figured that i could do something like this:
class Registrazione(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
buttons = GridLayout(cols=4)
for i in range(x):
buttons.add_widget(Button())
self.add_widget(buttons)
and this way, everything works properly. Now, let's say I want to add a single button under all of them, I can do
class Registrazione(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
base = BoxLayout(orientation='vertical')
buttons = GridLayout(cols=4)
for i in range(x):
buttons.add_widget(Button())
base.add_widget(buttons)
base.add_widget(Button(text='another button'))
self.add_widget(base)
and again, this works fine. My question is: can I write some of this stuff in my .kv file? Expecially the button that goes under everything, can I add it through the .kv file? It's a lot easier there, and if for some reason I want to add a lot more things under the previously mentioned buttons, it would be much faster and easier to write all that code in the .kv file.
I hope it's clear, and that you can help me out.
Thanks a lot to everyone that answers
Related
I am reading a sensor and want to display its output as a decimal number in a GUI using PyQt5. I have found a number of tutorials that point out the label.setText('myStr') function. This does not work for my setup, however, because I need to update the field based on the input from another function. I'm not very familiar with PyQt5 yet, and I would appreciate any insight into how this problem ought to be approached.
Note: (I am using LCM to acquire data from a Raspberry Pi. I'm not sure that that is relevant to the problem, but it helps explain my code below.)
Here is what I am trying to do:
class Home_Win(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
loadUi("sensor_interface.ui", self)
self.label_temp.setText('temperature') #Just to verify that I can change it from here
def acquire_sensors(self):
temp = 0 #Make variable available outside nested function
def listen(channel, data):
msg=sensor_data.decode(data)
temp = msg.temperature
lc = lcm.LCM()
subscription = lc.subscribe("sensor_data_0", listen)
while True:
lc.handle()
self.label_temp.setText(str(temp))
Any thoughts on how I can update the GUI to display the readings I am getting from my sensors?
Thanks!
You're almost there. All you need to do is to save the ui in an instance variable in __init__:
self.ui = loadUi("sensor_interface.ui", self)
Then, assuming label_temp is the name of your QLabel widget, just do:
self.ui.label_temp.setText(str(temp))
It turned out that I needed to add repaint(). I also switched to a QLineEdit as this seemed to work better for me. So inside the while loop I now have:
self.ui.lineEdit_temp.setText(str(temp))
self.ui.lineEdit_temp.repaint()
This now outputs live updates to the GUI while reading the data stream.
Ï'm trying to make a simple code that can automatically perform a sequence of smaller tasks on the click of a button. There's some information that currently needs to be punched into several word and excel sheets and webpages at work; it's time consuming and boring. My idea has been to create a tkinter window that allows the user to enter the necessary information, which is subsequently stored in a .csv file. I made it work without the use of classes, but when researching Tkinter, I realised that it's good practise to use classes. Problem is, I can't make it work when I put the entry widget into a class. This code works, but doesn't apply class(es):
def newprojectinput():
task_number_s = task_number_e.get()
#code is written to .csv in this method
my_window = Tk()
generate_b = Button(my_window, text="Make new project", command=newprojectinput)
generate_b.grid(row=12,column=1)
task_number_e = Entry(my_window)
task_number_e.grid(row=0,column=1)
my_window.mainloop()
This doesn't work:
def newprojectinput():
task_number_s = task_number_e.get()
#code is written to .csv in this method
class Toplevel_new_project:
def __init__(self, top=None):
self.Frame1 = tk.Frame(top)
self.task_number_e = tk.Entry(self.Frame1)
self.generate_b = tk.Button(self.Frame1, command=newprojectinput)
I would appreciate it if someone could take the time to provide optimal code and maybe briefly explain why the previous code doesn't work.
So I've created a GUI for a program I'm writing, and what I'm currently stuck on is the running of the calculations I want it to perform. I've done everything in Python 3.5, with a Kivy GUI build string to create the tabs (using tabbed panel and screen manager). I've got a button at the bottom of the tab to which this question pertains which says "Calculate" and should be taking the values of the text entries and operating them as part of the equation I want them to do.
Is the
.get
function going to be helpful in this case for doing this, or do I want to call more like:
class TabSys(TabbedPanel):
def calculate_psc_clicked(self):
#when they click the button which is id'd as "calculate_psc," this function
#will pull the values and perform the calculations
self.Cp_entry = self.Cp_entry.text
self.P_entry = self.P_entry.text
self.lhv_entry = self.lhv_entry.text
The above code is the TabSys class for my build string in kivy language, after it comes the
class nyce_meemApp(App):
def build(self):
return TabSys()
if __name__ == '__main__':
nyce_meemApp().run()
To actually run all the code. I don't want to inundate the question with code, so I'll leave it there, and I can put up any other pieces of code that anybody wants (if need be I can share the file).
Thanks
I'm working on a text-based game in Python using Tkinter. All the time the window contains a Label and a few Buttons (mostly 3). If it didn't have GUI, I could just use Pickle or even Python i/o (.txt file) to save data and later retrieve it. But what is the best way to tell the program to load the exact widgets without losing bindings, buttons' commands, classes etc.? P.S.: Buttons lead to cleaning the frame of widgets and summoning new widgets. I'm thinking of assigning a lambda (button's command) to a variable and then saving it (Pickle?) to be able to load it in the future and get the right point in the plot. Should I go for it or is there a better, alternative way to accomplish the thing? (If using lambda may work, I'd still be grateful to see your way of doing that.)
You need to save stuff in some kind of config file. In generel I'd recommend JSON and YAML as file formats also ini for ease of parsing.
Also, do not forget about the windows registry (portability lost then though).
My understanding was that you need a widget manager, to put them where you want and it is easy to pick up values.
Create a new class called Manager, make two functions, _setNewWidget, _deleteWidget, like this:
class Manager():
def __init__(self, *args, **kwargs):
objects = {}
def _createButton(self, frame, id, function, etc):
# object[id] = frame.Button(function, etc, ...) i dnt' know sintaxes, but this is the way
def _deleteWidget(self, id):
# object[id] = None or del(object[id]) same here
To get, just:
manager = Manager()
manager._createWidget("button_fase_one", frameTk, etc, etc)
manager.objects["button_fase_one"].changeFrame() # example
print(manager.objects["button_fase_one"].text)
In this way u can create objects and blit where u want.
To save data just make another function and save as json.
I'm writing an app that doesn't have a main window (it runs inside a Python interpreter in another app), and I thought I had a good solution for getting Tkinter to cooperate--I made the Tkinter.Tk class into a Borg.
class RootWindow(Tk):
""" Invisible window that serves as the default parent
of all others.
"""
groupDict = {}
def __init__(self):
self.__dict__ = self.groupDict
if self.__dict__ == {}: # first instance
Tk.__init__(self)
self.withdraw()
Then I have my Windows, which are subclassed from Tkinter.Toplevel, default to parent=RootWindow(). The result should be that I can create any number of Windows and they'll use the same root.
It works once fine for the first Window, but after that things get all messed up. :(
see pic
What am I doing wrong? Is this even a feasible solution?
Thanks
EDIT: I should add that even though there's other stuff running in the picture, the problem can be duplicated just by using RootWindow as the parent of a Tkinter.Toplevel.
EDIT: I overrode Window.mainloop so everything uses the RootWindow event loop.
def mainloop(self):
self.master.wait_window(self)
Then I create each visible window like this:
test = Window()
test.mainloop()
It seems to work because the windows do show up, but their contents are packed in an odd way that's hard to describe. It alternates between no contents at all and having everything squished horizontally and expanded vertically.
One problem appears to be that you are forgetting to start the event loop. Or, based on further edits of your question, you may be starting more than one main loop. You need exactly one main loop that is run from the root window.
Tkinter certainly allows an arbitrary number of top level windows, but your question doesn't appear to have enough details to show what is wrong unless my first guess is correct.