I am trying to develop a GUI using Tkinter and Python2.7 by following a few tutorials and their documentation. Right now i am stuck on how to keep my frame a constant size (Because i want to have a nice background).
I have tried to use geometry() function from their documentation but always returns with an error - geometry attribute not found
import Tkinter as tk
import ttk
class Application(tk.Tk):
def __init__(self, *args, **kwargs):
# Initialize Tkinter
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "ScraperBot")
tk.Tk.geometry('250x250')
# Make a container
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
# Define Frames
self.frames = {}
for myFrame in (HomePage, PageOne, PageTwo):
frame = myFrame(container, self)
self.frames[myFrame] = frame
frame.grid(row=0, column=0, sticky="nsew")
# Which frame do we wanna display?
self.show_frame(HomePage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# Make a Label
label = ttk.Label(self, text="HomePage", font=LARGE_FONT)
label.pack(pady=10, padx=10) # Padding on top and bottom
# Add a Button to navigate from one page to another
button1 = tk.Button(self, text="Go to Page_1", fg="red",
command= lambda: controller.show_frame(PageOne))
button1.pack()
# Add a Button to navigate from one page to another
button6 = tk.Button(self, text="Go to Page_2", fg="green",
command= lambda: controller.show_frame(PageTwo))
button6.pack()
def button_Function(parameter):
print(parameter)
app = Application()
app.mainloop()
I am using Tkinter and would like to have the option to clear my graph and draw a new one in its place. I'm not sure what to put in my callback to do this. The best I can do so far is to replace the graph with a white box. The new graph is drawn underneath (which isn't ideal) and also appears as a blank white box for some reason. Apologies for asking such a basic question but I'm new to python and couldn't find an example using subplots on here.
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import Tkinter as tk
from Tkinter import *
import ttk
class Helmholtz_App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Helmholtz Coils Data")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (PageOne,PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(PageOne)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
fig1 = Figure(figsize=(5,5), dpi=100)
a = fig1.add_subplot(111)
def callback():
volt=[[0,1,2,3,4],[0,1,2,3,4]]
a.plot(volt[1],volt[0],'bo')
canvas = FigureCanvasTkAgg(fig1, self)
canvas.show()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2TkAgg(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
def ClearCallback():
#problem line
#~~~~~~~~~~~
fig1.clf()
# ~~~~~~~~~~
clearbutton.destroy()
clearbutton=ttk.Button(self, text="Clear", command=ClearCallback)
clearbutton.pack()
b=ttk.Button(self, text="Plot Data", command=callback)
b.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
app = Helmholtz_App()
app.mainloop()
The code is based on this tutorial 1
I want the code to work so the "take data" button creates a graph, and the "clear" button removes that graph. Then when the "take data" button is pressed again it will put a new graph in the same place with none of the data from the old graph present.
Here is the
#!/usr/bin/python
# -*- coding: ISO-8859-1 -*-
from gi.repository import GLib, Gtk, Gio
import sys
from gi.repository import Gdk
from gi.repository.GdkPixbuf import Pixbuf, InterpType
class MyAbout(Gtk.AboutDialog):
__gtype_name__ = 'MyAbout' # nom pour css
def __init__(self,title='',version="1.0",\
authors=["Francis"],\
name="PyGObject Tutorial",\
comment="New tutorial on using Python with GTK+ 3",\
website="http://www.learngtk.org/",\
label="LearnGTK Website",\
filename=None,\
size_x=100, size_y=100):
Gtk.AboutDialog.__init__(self)
self.set_title(title)
self.set_version(version)
self.set_authors(authors)
if filename is not None:
file = filename
else:
file = "/home/francis/Documents/Python-linux/demo_gtk2/battery.png"
pixbuf = Pixbuf.new_from_file_at_size(file,size_x, size_y)
self.set_logo(pixbuf)
self.set_name(name)
self.set_comments(comment)
self.set_website(website)
self.set_website_label(label)
__version__ = "V1_30"
class MyApp_root(object):
""" just a little app with few menu """
def __init__(self):
GLib.set_application_name('My App')
self.app = Gtk.Application.new('org.example.test', 0)
self.app.connect('startup', self.on_app_startup)
self.app.connect('activate', self.on_app_activate)
self.app.connect('shutdown', self.on_app_shutdown)
def add_sub_menu(self,texte, menu):
""" just add submenu to menu return need reference to sub_menu"""
submenu = Gio.Menu()
menu.append_submenu(texte, submenu)
return submenu
def add_menu_bar(self,app):
""" just add function menubar app need refernce to app_menu"""
menu_bar = Gio.Menu()
app.set_menubar(menu_bar)
return menu_bar
def add_section(self,app):
""" just add a section
note between 2 sections there is a separator"""
section = Gio.Menu()
app.append_section(None, section)
return section
def add_simple_action(self, app, name, callback):
""" in order to create callback fonction linked menu"""
action = Gio.SimpleAction.new(name, None)
action.connect('activate', callback)
app.add_action(action)
def add_menuitem(self,section,text,link,attribut_type=None, attribut_value=None):
""" just add a item with parameter """
item = Gio.MenuItem.new(text,link)
if attribut_type is not None:
# example item.set_attribute_value("accel", GLib.Variant("s", "<Control>Q"))
item.set_attribute_value(attribut_type, attribut_value)
section.append_item(item)
def run(self, argv):
""" in order to run class """
self.app.run(argv)
def on_app_startup(self, app):
""" auto start app in window, set menu and call back
standard design in python callback action is action_cb"""
self.window = Gtk.ApplicationWindow.new(app)
self.window.set_default_size(640, 480)
self.window.set_title('AppMenu Demo')
app.add_window(self.window)
# # add Appmenu to app
self.app_menu = Gio.Menu()
section = self.add_section(self.app_menu)
self.add_menuitem(section,'Quit', 'app.quit',"accel", GLib.Variant("s", "<Control>Q"))
# it's necessary to link app-menu to app after section definition if not accelerator don't operate
app.set_app_menu(self.app_menu)
self.add_simple_action(app,'quit',self.quit_cb)
self.add_simple_action(app,'histo',self.histo_cb)
self.add_simple_action(app,'about',self.about_cb)
self.add_simple_action(app,'help',self.help_cb)
# # Menu bar attached app
self.menu_bar = self.add_menu_bar(app)
#---création submenu1
self.submenu1 = self.add_sub_menu('Miscellaneous',self.menu_bar)
#---création de section 3
section3 = self.add_section(self.submenu1)
#---gestion des item
self.add_menuitem(section3,'Help', 'app.help',"accel", GLib.Variant("s", "<Control>H"))
self.add_menuitem(section3,'About', 'app.about')
self.add_menuitem(section3,'Historic version', 'app.histo')
#code writed here in order to debug
submenu1 = self.add_sub_menu('Miscellaneous 1',self.menu_bar)
# # add section to submenu
section1 = self.add_section(submenu1)
# add item to section
self.add_simple_action(app,'pref',self.pref_cb)
self.add_menuitem(section1,'Preference', 'app.pref',"accel", GLib.Variant("s", "<Control>P"))
def on_app_activate(self, app):
self.window.show_all()
def on_app_shutdown(self, app):
pass
#here only in order to debug corresponding part and deleted after
def pref_cb(self, action, data=None):
print 'action preference not dev !!!!!!!!'
# end block to be deleted
def histo_cb(self, action, data=None):
print 'historique des versions'
print 'Version 1.30 add root class with basic menu '
print '#Version 1.31 > a class inherit MyApp_root and try to add something'
def about_cb(self, action, data=None):
about = MyAbout(version=__version__)
about.run()
def help_cb(self, action, data=None):
print "aide non developpe"
def quit_cb(self, action, data=None):
self.app.quit()
class MyAppNew(MyApp_root):
""" inherit class MyApp_root """
def __init__(self):
MyApp_root.__init__(self);
# # add submenu attached menu_bar
submenu = self.add_sub_menu('Miscellaneous next',self.menubar) #error here AttributeError: 'MyAppNew' object has no attribute 'menubar'
section1 = self.add_section(submenu)
# add item to section
self.add_menuitem(section1,'work hard', 'app.work')
self.add_simple_action(app,'work',self.work_cb)
def run(self, argv):
""" in order to run class """
pass # ??????
# here start to transfer all call back not necessary in root class
def work_cb(self, action, data=None):
print " It's very hard for me to make a class inherit class MyApp_root"
# to adapt a new help
def help_cb(self, action, data=None):
print "How to implement polymorhisme in order to change action in th child class here ??"
if __name__ == '__main__':
new_test = True
if new_test:
app = MyAppNew()
else:
application = MyApp_root()
application.run(sys.argv)
Hello everybody,
I know why error occur , self.menubar is not created in the init of root MyApp_root. But its created with self.on_app_startup when event 'startup' occur.
during start running class. Ok it's said
but now who could help me and say me how I must operate to add some new submenu in MyAppNew. Thank a lot by advance
In this case assuming you really want to work like this the solution is to make sure that you add the new submenu after self.menu_bar is created.
In your case the easiest way to do this is adding a function like self.insert_custom_menu (or something like that) in MyApp_root which you will overwrite in MyAppNew. If you then have a function call to this function in on_app_startup it will be easy to add the new menu options
So for example in MyApp_root the function will be like this:
def insert_custom_menu(self):
pass
While in MyAppNew the function will be like this:
def insert_custom_menu(self):
submenu = self.add_sub_menu('Miscellaneous next',self.menubar)
section1 = self.add_section(submenu)
self.add_menuitem(section1,'work hard', 'app.work')
The reason why this will work is that MyAppNew does not try to add something to a menu during init while the menu is only create after the startup signal. With the above solution the custom part of the menu is also loaded after startup which resolves the issue at hand.
In order to help. A example of inherit class Gtk.Application. It's running on my linux except bug unity on top menu ""Unknown Application Name"" appear instead of really name it's know.
it's just a modest contribution
#!/usr/bin/python
# -*- coding: ISO-8859-1 -*-
from gi.repository import GLib, Gtk, Gio
import sys
from gi.repository import Gdk
from gi.repository.GdkPixbuf import Pixbuf, InterpType
class MyAbout(Gtk.AboutDialog):
__gtype_name__ = 'MyAbout' # nom pour css
def __init__(self,title='',version="1.0",\
authors=["Francis"],\
name="PyGObject Tutorial",\
comment="New tutorial on using Python with GTK+ 3",\
website="http://www.learngtk.org/",\
label="LearnGTK Website",\
filename=None,\
size_x=100, size_y=100):
Gtk.AboutDialog.__init__(self)
self.set_title(title)
self.set_version(version)
self.set_authors(authors)
if filename is not None:
file = filename
else:
file = "/home/francis/Documents/Python-linux/demo_gtk3/battery.png"
try:
pixbuf = Pixbuf.new_from_file_at_size(file,size_x, size_y)
self.set_logo(pixbuf)
except:
self.set_name(name)
self.set_comments(comment)
self.set_website(website)
self.set_website_label(label)
__version__ = "V1_30"
class MyApp_root(object):
""" just a little app with few menu """
def __init__(self):
GLib.set_application_name('My App')
self.app = Gtk.Application.new('org.example.test', 0)
self.app.connect('startup', self.on_app_startup)
self.app.connect('activate', self.on_app_activate)
self.app.connect('shutdown', self.on_app_shutdown)
def add_sub_menu(self,texte, menu):
""" just add submenu to menu return need reference to sub_menu"""
submenu = Gio.Menu()
menu.append_submenu(texte, submenu)
return submenu
def add_menu_bar(self,app):
""" just add function menubar app need refernce to app_menu"""
menu_bar = Gio.Menu()
app.set_menubar(menu_bar)
return menu_bar
def add_section(self,app):
""" just add a section
note between 2 sections there is a separator"""
section = Gio.Menu()
app.append_section(None, section)
return section
def add_simple_action(self, app, name, callback):
""" in order to create callback fonction linked menu"""
action = Gio.SimpleAction.new(name, None)
action.connect('activate', callback)
app.add_action(action)
def add_menuitem(self,section,text,link,attribut_type=None, attribut_value=None):
""" just add a item with parameter """
item = Gio.MenuItem.new(text,link)
if attribut_type is not None:
# example item.set_attribute_value("accel", GLib.Variant("s", "<Control>Q"))
item.set_attribute_value(attribut_type, attribut_value)
section.append_item(item)
def run(self, argv):
""" in order to run class """
self.app.run(argv)
def insert_custom_menu(self):
""" in order to add custom menu later"""
pass
def insert_custom_submenu_first(self):
""" in order to add something in the first submenu before Quit """
## current section is self.custom_section
pass
def insert_custom_submenu_last(self):
""" in order to add something in the last submenu before Quit """
## current section is self.custom_section_last
pass
def on_app_startup(self, app):
""" auto start app in window, set menu and call back
standard design in python callback action is action_cb"""
self.window = Gtk.ApplicationWindow.new(app)
self.window.set_default_size(640, 480)
self.window.set_title('AppMenu Demo')
app.add_window(self.window)
# # add Appmenu to app
self.app_menu = Gio.Menu()
# insert something in the first submenu in dedicated section
self.custom_section = self.add_section(self.app_menu)
self.insert_custom_submenu_first()
# last section to quit action
section_last = self.add_section(self.app_menu)
self.add_menuitem(section_last,'Quit', 'app.quit',"accel", GLib.Variant("s", "<Control>Q"))
# it's necessary to link app-menu to app after section definition if not, accelerator don't operate
app.set_app_menu(self.app_menu)
self.add_simple_action(app,'quit',self.quit_cb)
self.add_simple_action(app,'histo',self.histo_cb)
self.add_simple_action(app,'about',self.about_cb)
self.add_simple_action(app,'help',self.help_cb)
# # Menu bar attached app
self.menu_bar = self.add_menu_bar(app)
# planed if custum menu
self.insert_custom_menu()
#---make submenu1
self.submenu1 = self.add_sub_menu('Miscellaneous',self.menu_bar)
#---make section 3
section3 = self.add_section(self.submenu1)
#---item management
self.add_menuitem(section3,'Help', 'app.help',"accel", GLib.Variant("s", "<Control>H"))
self.add_menuitem(section3,'About', 'app.about')
self.add_menuitem(section3,'Historic version', 'app.histo')
## last section dedicated to custom add in last submenu
self.custom_section_last= self.add_section(self.submenu1)
self.insert_custom_submenu_last()
def on_app_activate(self, app):
self.window.show_all()
def on_app_shutdown(self, app):
pass
def histo_cb(self, action, data=None):
print 'historique des versions'
print 'Version 1.30 add root class with basic menu '
print '#Version 1.31 > a class inherit MyApp_root and try to add something'
def about_cb(self, action, data=None):
""" about app"""
about = MyAbout(version=__version__)
about.run()
def help_cb(self, action, data=None):
""" in order to help user """
print "aide non developpe"
def quit_cb(self, action, data=None):
self.app.quit()
class MyAppNew(MyApp_root):
""" inherit class MyApp_root """
def __init__(self):
MyApp_root.__init__(self);
def run(self, argv):
""" in order to run class """
self.app.run(argv)
def insert_custom_submenu_first(self):
""" in order to add something in the first submenu before Quit """
## current section is self.custom_section
self.add_menuitem(self.custom_section,'something 1', 'app.work1')
self.add_simple_action(self.app,'work1',self.work1_cb)
def insert_custom_menu(self):
""" custom menu in child class"""
submenu1 = self.add_sub_menu('Miscellaneous next',self.menu_bar)
# # add section to submenu
section1 = self.add_section(submenu1)
# add item to section
self.add_menuitem(section1,'work hard', 'app.work')
self.add_simple_action(self.app,'work',self.work_cb)
def insert_custom_submenu_last(self):
""" in order to add something in the last submenu before Quit """
## current section is self.custom_section_last
self.add_menuitem(self.custom_section_last,'something in the last submenu', 'app.work2')
self.add_simple_action(self.app,'work2',self.work2_cb)
def work_cb(self, action, data=None):
print " It's very hard for me to make a class inherit class MyApp_root"
def work1_cb(self, action, data=None):
print " something 1"
def work2_cb(self, action, data=None):
print " ready to do something in the last submenu"
# to adapt a new help
def help_cb(self, action, data=None):
print "How to implement overwrite method in order to change action in child class here"
if __name__ == '__main__':
app = MyAppNew()
app.run(sys.argv)
The user enters values using line edits on the MyWidget screen and then presses the Enter button. This opens the MyDialog screen on which data will be plotted when the Run button is pressed. How can I make the line edit data accessible to run in MyDialog for plotting? Or, is there a better way of doing this which wouldn't require passing variables between classes? My program is based on this answer.
from PyQt4 import QtCore, QtGui, uic
# Import Qt widgets
from matplotlib.backends.backend_qt4agg \
import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg \
import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
GUI_FILE = "Minimal_UI.ui" # GUI with line edit and 'enter' button
form_class = uic.loadUiType(GUI_FILE)[0]
class MyWidget(QtGui.QWidget, form_class):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
self.setupUi(self)
self.pushButton_Enter.clicked.connect(self.on_pushButton_clicked)
self.dialogTextBrowser = MyDialog(self)
#QtCore.pyqtSlot()
def on_pushButton_clicked(self):
# I'd like to be able to pass Temp_0 to the run method
self.Temp_0 = self.lineEdit_Temp_0.text()
self.dialogTextBrowser.exec_()
class MyDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(MyDialog, self).__init__(parent)
self.fig = Figure()
self.canvas = FigureCanvas(self.fig)
self.toolbar = NavigationToolbar(self.canvas, self)
self.run_button = QtGui.QPushButton('Run')
self.run_button.clicked.connect(self.run)
self.stop_button = QtGui.QPushButton('Stop')
self.stop_button.clicked.connect(self.stop)
layout = QtGui.QVBoxLayout()
# Widgets are stacked in the order they are added
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.run_button)
layout.addWidget(self.stop_button)
self.setLayout(layout)
def run(self):
# Create axes
ax = self.fig.add_subplot(111)
# Discard the old graphs
ax.hold(False)
# Plot data--I'd like to be able to use line edit data here
ax.plot([1, 2, 3, 4], '*-')
# Refresh canvas
self.canvas.draw()
def stop(self):
print 'Stop Pressed'
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWidget')
main = MyWidget()
main.show()
sys.exit(app.exec_())
MyDialog constructor has an attribute parent.
With the code bellow, you create an instance of MyDialog with MyWidget as a parent:
self.dialogTextBrowser = MyDialog(self)
Two ways for a widget to access data from it's parent:
Use the parent attribute in the __init__ function
self.lineEditData=parent.lineEdit.text()
Use the parent() method anywhere
def run(self):
self.lineEditData=self.parent().lineEdit.text()
I say it depends on how your suppose to use the application. If your suppose to fill the lineEdit once click and get a plot, I would use the parent attribute or directly pass the data in the __init__ function.
But if the user can go back to the lineEdit, change something, and click "run" again, then you should use the parent() method in run.
I am trying to make an android application...I am trying to switch from menu to server or client according to user input...but i am not able to switch from one class to another...main thing which pissed me off is that print statement inside ServerScreen is working but other part is not working...don't know why
Code:---
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
class MenuScreen(Screen):
def __init__(self, **kwargs):
super(MenuScreen, self).__init__(**kwargs)
def Server(instance):
self.clear_widgets()
self.add_widget(Label ( text = 'Inside server function'))
server = ServerScreen()
#return server
#server.function()
self.add_widget(Label ( text = 'What Type Of Service You Want...???'))
button1 = Button(text = 'Server',size_hint = (None,None),pos = (0,0))
self.add_widget(button1)
button1.bind(on_press = Server)
button2 = Button(text = 'Client',size_hint = (None,None),pos = (100,0))
self.add_widget(button2)
#button2.bind(on_press = Client)
class ServerScreen(Screen):
def __init__(self, **kwargs):
super(ServerScreen, self).__init__(**kwargs)
print('Inside server screen')
self.clear_widgets()
self.add_widget(Label (text = 'Working As A Server'))
print("Hellooooooooooo")
sm = ScreenManager()
sm.add_widget(MenuScreen(name='Menu'))
sm.add_widget(ServerScreen(name='Server'))
#sm.add_widget(ClientScreen(name='Client'))
class FileApp(App):
def build(self):
#return Menu()
return sm
if __name__ == '__main__':
FileApp().run()
In which part i am making mistake...please point out that part & provide how can i solve that...
Output--->
Inside server screen
Hellooooooooooo
Look at my solution inspired by this excellent comment from inclement : Kivy: Changing screens in screen manager with an on_press event
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
class MenuScreen(Screen):
def switching_function(*args):
global sm
sm.current = 'Server'
def __init__(self, **kwargs):
super(MenuScreen, self).__init__(**kwargs)
# def Server(instance):
# self.clear_widgets()
# self.add_widget(Label ( text = 'Inside server function'))
# server = ServerScreen()
# #return server
# #server.function()
self.add_widget(Label ( text = 'What Type Of Service You Want...???'))
button1 = Button(text = 'Server',size_hint = (None,None),pos = (0,0))
self.add_widget(button1)
# button1.bind(on_press = Server)
button1.bind(on_press = self.switching_function)
button2 = Button(text = 'Client',size_hint = (None,None),pos = (100,0))
self.add_widget(button2)
#button2.bind(on_press = Client)
class ServerScreen(Screen):
def __init__(self, **kwargs):
super(ServerScreen, self).__init__(**kwargs)
print('Inside server screen')
self.clear_widgets()
self.add_widget(Label (text = 'Working As A Server'))
print("Hellooooooooooo")
sm = ScreenManager()
sm.add_widget(MenuScreen(name='Menu'))
sm.add_widget(ServerScreen(name='Server'))
#sm.add_widget(ClientScreen(name='Client'))
class FileApp(App):
def build(self):
#return Menu()
return sm
The problem is with server = ServerScreen() inside
def Server(instance):
self.clear_widgets()
self.add_widget(Label ( text = 'Inside server function'))
server = ServerScreen()
#return server
#server.function()
It creates a new ServerScreen, not the ServerScreen which is actually displayed at the moment (so
Inside server screen
Hellooooooooooo
is displayed, but the ScreenManager has no idea that this additional Screen is existing.