I have a main python program A.py that calls a GUI Gtk python program, B.py, to display a window.
I want this window being color buttons and when I click on one, the main A.py code recover a value, the RGB color value.
A.py
import B
c = B.gui_color()
print(c)
B.py
class W(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="colors")
self.box = Gtk.Box(spacing=0, homogeneous=True)
self.add(self.box)
colors = j.load("colors.json")
for c in colors:
b = Gtk.Button()
b.connect("clicked", self.return_color, c["value"])
# x257 to get the GTK color
b.modify_bg(Gtk.StateType.NORMAL, Gdk.Color(c["value"][0] * 257, c["value"][1] * 257, c["value"][2] * 257))
self.box.pack_start(b, True, True, 0)
def return_color(self, widget, *color):
self.close()
return color[0]
def gui_color():
w = W()
w.connect("destroy", Gtk.main_quit)
w.show_all()
Gtk.main()
Everything is ok with the program, I get my window with multiple color buttons, however I can not figure out how to recover the color I clicked on. The return action in the return_color doesn't return to the A.py program. How can I perform that? Should I use stdout with print? I precise that after having clicking, I would like to do others actions that won't need a GUI at all.
Before return color[0] in the return_color do self.selected_color = color[0], after Gtk.main() do return w.selected_color
Related
I've been having this problem with a python program I am making where if I display a TopLevel window, in this case my Help Menu, then withdraw it then try to display it again I get the following error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__
return self.func(*args)
File "C:\Users\****\Documents\GitHub\ProjectName\ProjectName\GUI.py", line 60, in displayHelp
self.helpMenu.display();
File "C:\Users\****\Documents\GitHub\ProjectName\ProjectName\HelpMenu.py", line 35, in display
self.deiconify();
File "C:\Python34\lib\tkinter\__init__.py", line 1646, in wm_deiconify
return self.tk.call('wm', 'deiconify', self._w)
_tkinter.TclError: bad window path name ".60000336"
The error first happened when I was withdrawing from within HelpMenu.py and using deiconify to redisplay it from the GUI.py file.
Since then I have tried multiple ways to fix the problem including calling deiconify from within HelpMenu.py and updating the copy of help menu stored in the GUI when I withdraw it.
I am running Python 3.4.2
I have already done extensive searches online and failed to find a solution to my problem. I have found other mentions of this error but they either didn't relate to my situation or their solutions did not work.
Here is the entire code for the HelpMenu.py followed by an extract from GUI.py that retains the functionality to reproduce the error but has other code removed.
#!/usr/bin/python
try:
from Tkinter import *
except ImportError:
from tkinter import *
class HelpMenu(Toplevel):
def __init__(self, parent, observer):
Toplevel.__init__(self);
self.observer = observer;#Observer is the GUI, this is here just so I can update the GUI when I withdraw this window
self.setup();
self.withdraw();
self.protocol('WM_DELETE_WINDOW', self.quit());#Changes the close button to just hide the window
def setup(self):
self.columnconfigure(0,weight=1);
w = 400;#Sets up the window position on the screen
h = 150;
sw = self.winfo_screenwidth();
sh = self.winfo_screenheight();
x=(sw-w)/2;
y =(sh-h)/2;
self.update();
self.geometry('%dx%d+%d+%d' % (w,h,x,y));
self.resizable(width=0, height=0);
self.grid();
self.title("Help Menu");
def quit(self):#Hides the window
self.withdraw();
self.observer.updateHelp(self);
def display(self):#Re-displays the window
self.deiconify();
Here is code taken from GUI.py and modified to only have the code needed to reproduce the issue.
#!/usr/bin/python
#Allows compatibility with any version of Python by checking for both versions of Tkinter
try:
from Tkinter import *
except ImportError:
from tkinter import *
#Imports the AutoCompleteEntry
from HelpMenu import HelpMenu
class UI(Tk):
def initialize(self):
#Handles setting up most of the GUI
w = 500;#Window width
h = 500;#Window height
sw = self.winfo_screenwidth();#Gets screen width
sh = self.winfo_screenheight();#Gets screen height
x=(sw-w)/2;#Calculates the x position for the left side of the window that allows it to be placed in the center of the screen
y =(sh-h)/2;#Calculates the y position for the top of the window that allows it to be placed in the center of the screen
self.update();#Forces and update on the window
self.geometry('%dx%d+%d+%d' % (w,h,x,y));#Sets the windows width, height and position
self.minsize(int(w),int(h/2));#Sets the minimum size of the window
self.configureMenu();
def updateHelp(self, helpMenu):
self.helpMenu=helpMenu;
def displayHelp(self):
self.helpMenu.display();
def configureMenu(self):
#Handles configuring and setting up the menus
menu = Menu(self);#Setup the menu bar
menu.add_command(label="Help",command=self.displayHelp);
self.config(menu=menu);
def __init__(self, parent):
#Handles the initial call to create a GUI
Tk.__init__(self,parent);#Parent constructor
self.parent = parent;#Store the parent
self.initialize();#Initilize the GUI
self.helpMenu = HelpMenu(self, self);
self.mainloop();#Start the main loop
if __name__ == "__main__":
import sys
main = UI(None);
One last note, I am slightly new to Python, so there might be other errors in my code and while I wont mind if they get pointed out, the main focus I have right now is fixing this path name error.
EDIT:Almost a month now and I have still not found a solution to the problem. Any help would be great but at this point I am probably going to have to abandon my project.
So, after a break I went back to look at this problem again.
Turns out that the issue was self.protocol('WM_DELETE_WINDOW', self.quit()) was not actually calling self.quit() and was destroying the window completely.
A quick change to self.protocol('WM_DELETE_WINDOW', self.quit) seems to have fixed it.
I think maybe the comma causes the problem. Try write it like this:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
try:
from Tkinter import *
except ImportError:
from tkinter import *
class HelpMenu(Toplevel):
def __init__(self, parent, observer):
Toplevel.__init__(self)
self.observer = observer # Observer is the GUI, this is here just so I can update the GUI when I withdraw this window
self.setup()
self.withdraw()
self.protocol('WM_DELETE_WINDOW', self.quit()) # Changes the close button to just hide the window
def setup(self):
self.columnconfigure(0, weight=1)
w = 400 # Sets up the window position on the screen
h = 150
sw = self.winfo_screenwidth()
sh = self.winfo_screenheight()
x = (sw - w) / 2
y = (sh - h) / 2
self.update()
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.resizable(width=0, height=0)
self.grid()
self.title("Help Menu")
def quit(self): # Hides the window
self.withdraw()
self.observer.updateHelp(self)
def display(self): # Re-displays the window
self.deiconify()
class UI(Tk):
def initialize(self):
# Handles setting up most of the GUI
w = 500 # Window width
h = 500 # Window height
sw = self.winfo_screenwidth() # Gets screen width
sh = self.winfo_screenheight() # Gets screen height
x = (sw - w) / 2 # Calculates the x position for the left side of the window that allows it to be placed in the center of the screen
y = (sh - h) / 2 # Calculates the y position for the top of the window that allows it to be placed in the center of the screen
self.update() # Forces and update on the window
self.geometry('%dx%d+%d+%d' % (w, h, x, y)) # Sets the windows width, height and position
self.minsize(int(w), int(h / 2)) # Sets the minimum size of the window
self.configureMenu()
def updateHelp(self, helpMenu):
self.helpMenu = helpMenu
def displayHelp(self):
self.helpMenu.display()
def configureMenu(self):
# Handles configuring and setting up the menus
menu = Menu(self) # Setup the menu bar
menu.add_command(label="Help", command=self.displayHelp)
self.config(menu=menu)
def __init__(self, parent):
# Handles the initial call to create a GUI
Tk.__init__(self, parent) # Parent constructor
self.parent = parent # Store the parent
self.initialize() # Initilize the GUI
self.helpMenu = HelpMenu(self, self)
self.mainloop() # Start the main loop
if __name__ == "__main__":
main = UI(None)
It works perfectly from myside.
Hi Iam using Python and GTK+. In my GUI I have 2 toolbars I want show first toolbar only if user moves mouse than hide it again after few seconds as for second toolbar I want to show it when user is on particular x,y coordinates.How can I achieve it ?
EDIT:
Iam creating some kind of media player so I want toolbars to disapear while user is not using mouse in case of playerMenu toolbar or if user doesn't move it to specific location in case of ribbonBar toolbar .Iam using GTK+ here is my code for toolbars:
class Player(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
def build_UI(self):
container=Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
ribbonBar=Gtk.Toolbar()
playerMenu=Gtk.Toolbar()
def mouse_moved(self):
#TO-DO here I should check cordinates for example I want to see if mouse.y=window.height-50px and I would like to show ribbonaBar
#after that Gdk.threads_add_timeout(1000,4000,ribbonBar.hide)
#TO-DO here I show playerMenu toolbar if mouse is moved
# smt like playerMenu.show()
#after that I would call Gdk.threads_add_timeout(1000,4000,playerMenu.hide)
# to hide it again after 4 seconds
I should connect my window to some mouse event but I don't know the event name and how can I get mouse.x and mouse.y?
Why do you want to do this? Trying to use widgets that disappear when you're not moving the mouse is rather annoying, IMHO.
But anyway...
To toggle the visibility of a widget use the show() and hide() methods, or map() and unmap() if you don't want the other widgets in your window to move around. To handle timing, use gobject.timeout_add(), and you'll need to connect() your window to "motion_notify_event" and set the appropriate event masks: gtk.gdk.POINTER_MOTION_MASK and probably gtk.gdk.POINTER_MOTION_HINT_MASK. The Event object that your motion_notify callback receives will contain x,y mouse coordinates.
At least, that's how I'd do it in GTK2; I don't know GTK3.
If you want more specific help you need to post some code.
I see that you've posted some code, but it doesn't have a lot of detail... But I understand that GTK can be a bit overwhelming. I haven't used it much in the last 5 years, so I'm a bit rusty, but I just started getting into it again a couple of months ago and thought your question would give me some good practice. :)
I won't claim that the code below is the best way to do this, but it works. And hopefully someone who is a GTK expert will come along with some improvements.
This program builds a simple Toolbar with a few buttons. It puts the Toolbar into a Frame to make it look nicer, and it puts the Frame into an Eventbox so we can receive events for everything in the Frame, i.e., the Toolbar and its ToolItems. The Toolbar only appears when the mouse pointer isn't moving and disappears after a few seconds, unless the pointer is hovering over the Toolbar.
This code also shows you how to get and process mouse x,y coordinates.
#!/usr/bin/env python
''' A framed toolbar that disappears when the pointer isn't moving
or hovering in the toolbar.
A response to the question at
http://stackoverflow.com/questions/26272684/how-can-i-show-hide-toolbar-depending-on-mouse-movements-and-mouse-position-insi
Written by PM 2Ring 2014.10.09
'''
import pygtk
pygtk.require('2.0')
import gtk
import gobject
if gtk.pygtk_version < (2, 4, 0):
print 'pygtk 2.4 or better required, aborting.'
exit(1)
class ToolbarDemo(object):
def button_cb(self, widget, data=None):
#print "Button '%s' %s clicked" % (data, widget)
print "Button '%s' clicked" % data
return True
def show_toolbar(self, show):
if show:
#self.frame.show()
self.frame.map()
else:
#self.frame.hide()
self.frame.unmap()
def timeout_cb(self):
self.show_toolbar(self.in_toolbar)
if not self.in_toolbar:
self.timer = False
return self.in_toolbar
def start_timer(self, interval):
self.timer = True
#Timer will restart if callback returns True
gobject.timeout_add(interval, self.timeout_cb)
def motion_notify_cb(self, widget, event):
if not self.timer:
#print (event.x, event.y)
self.show_toolbar(True)
self.start_timer(self.time_interval)
return True
def eventbox_cb(self, widget, event):
in_toolbar = event.type == gtk.gdk.ENTER_NOTIFY
#print event, in_toolbar
self.in_toolbar = in_toolbar
#### self.show_toolbar(in_toolbar) does BAD things :)
if in_toolbar:
self.show_toolbar(True)
return True
def quit(self, widget): gtk.main_quit()
def __init__(self):
#Is pointer over the toolbar Event box?
self.in_toolbar = False
#Is pointer motion timer running?
self.timer = False
#Time in milliseconds after point stops before toolbar is hidden
self.time_interval = 3000
self.window = win = gtk.Window(gtk.WINDOW_TOPLEVEL)
width = gtk.gdk.screen_width() // 2
height = gtk.gdk.screen_height() // 5
win.set_size_request(width, height)
win.set_title("Magic Toolbar demo")
win.set_border_width(10)
win.connect("destroy", self.quit)
#self.motion_handler = win.connect("motion_notify_event", self.motion_notify_cb)
win.connect("motion_notify_event", self.motion_notify_cb)
win.add_events(gtk.gdk.POINTER_MOTION_MASK |
gtk.gdk.POINTER_MOTION_HINT_MASK)
box = gtk.VBox()
box.show()
win.add(box)
#An EventBox to capture events inside Frame,
# i.e., for the Toolbar and its child widgets.
ebox = gtk.EventBox()
ebox.show()
ebox.set_above_child(True)
ebox.connect("enter_notify_event", self.eventbox_cb)
ebox.connect("leave_notify_event", self.eventbox_cb)
box.pack_start(ebox, expand=False)
self.frame = frame = gtk.Frame()
frame.show()
ebox.add(frame)
toolbar = gtk.Toolbar()
#toolbar.set_border_width(5)
toolbar.show()
frame.add(toolbar)
def make_toolbutton(text):
button = gtk.ToolButton(None, label=text)
#button.set_expand(True)
button.connect('clicked', self.button_cb, text)
button.show()
return button
def make_toolsep():
sep = gtk.SeparatorToolItem()
sep.set_expand(True)
#sep.set_draw(False)
sep.show()
return sep
for i in xrange(5):
button = make_toolbutton('ToolButton%s' % (chr(65+i)))
toolbar.insert(button, -1)
#toolbar.insert(make_toolsep(), -1)
for i in xrange(1, 9, 2):
toolbar.insert(make_toolsep(), i)
button = gtk.Button('_Quit')
button.show()
box.pack_end(button, False)
button.connect("clicked", self.quit)
win.show()
frame.unmap()
def main():
ToolbarDemo()
gtk.main()
if __name__ == "__main__":
main()
I'm making a Gtk.Window using PyGi Gtk3 and It adds an annoying border around widgets and the main window:
The border is this grey border between the two images and in the outside of the window. Anyone knows how to completely remove it? So the two images could be seamless joint together.
This is my code:
#!/usr/bin/python3
#encoding:utf-8
from gi.repository import Gtk, Gdk
class TestMainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Test Window")
self.set_resizable(False)
self.box = Gtk.Box(orientation='vertical')
self.add(self.box)
self.album_cover = Gtk.Image()
self.album_cover.set_from_file('../reference/album-cover.jpg')
self.box.pack_start(self.album_cover, True, True, 0)
self.album_cover2 = Gtk.Image()
self.album_cover2.set_from_file('../reference/album-cover.jpg')
self.box.pack_end(self.album_cover2, True, True, 0)
def main():
win = TestMainWindow()
win.connect('delete-event', Gtk.main_quit)
win.show_all()
Gtk.main()
if __name__ == '__main__':
main()
Give a try at setting the "margins" property inherited from GtkWidget to FALSE. In C this is done using g_object_set.
Using python and bindings (pyqt, pyopengl) I have created a simple 3D viewer. I would like to create some basic actions operated/triggered by user interaction. The program has 2 parts.
opengl widget:
class OpenGLWidget(QtOpenGL.QGLWidget):
def __init__(self, parent=None):
self.parent = parent
QtOpenGL.QGLWidget.__init__(self, parent)
...
def draw(self):
#here I would like to change colour of background from right mouse click menu
glClearColor(self.R,self.G,self.B,1)
main widget:
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.resize(initial_window_width, initial_window_height)
self.setWindowTitle('Window Name')
self.setMouseTracking(True)
# location of window on screen
self.setGeometry(5, 25, initial_window_width, initial_window_height)
self.createActions()
self.createMenus()
# sets opengl window in central widget position
self.OpenGLWidget = OpenGLWidget()
self.setCentralWidget(self.OpenGLWidget)
#pyqtSlot(QtCore.QPoint)
def contextMenuRequested(self,point):
menu = QtGui.QMenu()
action1 = menu.addAction("Blue")
self.connect(action1,SIGNAL("triggered()"), self,SLOT("Blue()"))
menu.exec_(self.mapToGlobal(point))
#pyqtSlot()
def Blue(self):
self.R = 0
self.G = 0
self.B = 1
The code that runs the entire program:
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.setContextMenuPolicy(QtCore.Qt.CustomContextMenu);
win.connect(win, SIGNAL("customContextMenuRequested(QPoint)"),
win, SLOT("contextMenuRequested(QPoint)"))
win.show()
sys.exit(app.exec_())
I would like to know how to change the values R, G, B in main widget that the background colour will change to blue in opengl widget.
Inside OpenGLWidget class add the following method:
def setColor(R, G, B):
self.R = R
self.G = G
self.B = B
Inside MainWindow in Blue() replace the existing code with the following one:
self.OpenGLWidget.setColor(0,0,1)
self.openGLWidget.draw() # or do whatever you want, variables are changed in `OpenGLWidget`
To set color to green, call setColor() with 0,1,0 parameters.
I can Add boxs and Tables
Also the Quit button does not work can someone edit that part of the code please
import gtk
class helloworld:
def close(self,widget):
print "I'm outta here"
gtk.main_quit()
def printit(self,widget,lab1):
print lab1.get_text()
def filllab(self,widget,lab1):
lab1.set_text(widget.get_text())
def __init__(self):
window = gtk.Window()
window.set_size_request(300,400)
vbox = gtk.VBox()
window.add(vbox)
lab1 = gtk.Label("shazbut")
# entry widget
ent1 = gtk.Entry()
ent1.connect("activate",self.filllab,lab1)
# quit
quitb = gtk.Button("quit",gtk.STOCK_QUIT)
quitb.set_size_request(50,100)
quitb.connect("destroy", gtk.main_quit)
printb = gtk.Button("print")
printb.connect("clicked",self.printit,lab1)
# Pack widgets in the vbox
vbox.add(ent1)
vbox.add(lab1)
vbox.add(quitb)
vbox.add(printb)
window.show_all()
helloworld()
gtk.main()
The "quit" button doesn't work because you connected the "destroy" signal to the button instead of the clicked signal
quitb.connect("clicked", gtk.main_quit)
Also, you forgot to connect the window destroy event (so the program will never exit when you click the window close button). Add
window.connect("destroy", gtk.main_quit)
To change the label properties use the pango attributes
def _add_attributes_to_label(self,label):
attr = pango.AttrList()
fg_color = pango.AttrForeground(65535, 0, 0,0,-1)
strike = pango.AttrStrikethrough(True,0,-1)
size = pango.AttrSize(30000, 0, -1)
attr.insert(fg_color)
attr.insert(size)
attr.insert(strike)
label.set_attributes(attr)
In your init function call the previous function like this:
self._add_attributes_to_label(lab1)
Follow this tutorial to know more about pango attributes.