Juxtapose a GtkMenuBar with other widgets? - menu

Is it possible to place a GtkMenuBar with other widgets together , instead of showing at the top of that window ?
Or i could use buttons , but when you hover your mouse over those buttons , the menu on the buttons won't just behave like a menu , which is , when you are close to one menu item , the menu pops down directly , without click , and other menu hide automatically. Can i make buttons like that ? Or other widgets that could have: label , image , and pop down menu item is cool.
Any ideas is appreciated.

Maybe the "enter-notify-event" and "leave-notify-event", connected to buttons, may help you do the thing, with for example, a popup menu show and hide respectively.
EDIT
I finally forgot those "enter" and "leave" events whose behaviour was a little complex, and just used the "motion-notify-event"...
Now I hope it is what you want !
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
class MenuExample:
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(200, 100)
self.window.set_title("GTK Menu Test")
self.window.connect("delete_event", lambda w,e: gtk.main_quit())
# A vbox to put a button in:
vbox = gtk.VBox(False, 0)
self.window.add(vbox)
vbox.show()
self.popped = False
# Create a button to simulate a menu
button = gtk.Button("press me")
vbox.pack_start(button, False, False, 2)
self.window.add_events(gtk.gdk.POINTER_MOTION_MASK)
self.window.connect("motion-notify-event", self.wakeup)
self.window.show_all()
self.bmenu = gtk.Button("A single entry menu")
self.bmenu.connect("clicked", self. menuitem_response, "Click on the magic menu !")
vbox.pack_start(self.bmenu, False, False, 2)
def wakeup(self, widget, event):
#print "Event number %d woke me up" % event.type
(x, y) = self.window.get_pointer()
if y < 30:
if self.popped == False:
self.popped = True
self.bmenu.show()
elif y > 60:
if self.popped == True:
self.popped = False
self.bmenu.hide()
# Print a string when a menu item is selected
def menuitem_response(self, widget, string):
print "%s" % string
def main():
gtk.main()
return 0
if __name__ == "__main__":
MenuExample()
main()

Related

Disable mouse double click event in tkinter

I am thinking about disabling the mouse double click event after one event. If i double click on an item from the list box the event disables until i press the Enable Double click button. How to archive this?
from tkinter import *
def go(event):
cs = Lb.curselection()
# Updating label text to selected option
w.config(text=Lb.get(cs))
# Setting Background Colour
for list in cs:
if list == 0:
top.configure(background='red')
elif list == 1:
top.configure(background='green')
elif list == 2:
top.configure(background='yellow')
elif list == 3:
top.configure(background='white')
top = Tk()
top.geometry('250x275')
top.title('Double Click')
# Creating Listbox
Lb = Listbox(top, height=6)
# Inserting items in Listbox
Lb.insert(0, 'Red')
Lb.insert(1, 'Green')
Lb.insert(2, 'Yellow')
Lb.insert(3, 'White')
# Binding double click with left mouse
# button with go function
Lb.bind('<Double-1>', go)
Lb.pack()
# Creating Edit box to show selected option
w = Label(top, text='Default')
w.pack()
# Creating Enable button to enable double clicking
enable_btn = Button(top, text = 'Enable Double Click')
enable_btn.pack(pady = 10)
top.mainloop()
To disable double-click, bind to that event and then have your function return the string "break". You can use a variable to trigger that behavior.
Start by defining a flag, and then a function that can set the flag:
double_click_enabled = False
def enable_double_clicking(enable):
global double_click_enabled
double_click_enabled = enabled
Next, define your button to call this function. In this example I'll show two buttons for enabling and disabling:
enable_btn = Button(top, text = 'Enable Double Click', command=lambda: enable_double_clicking(True))
disable_btn = Button(top, text = 'Disable Double Click', command=lambda: enable_double_clicking(False))
Finally, check for the flag at the top of your go function. If double-clicking is disabled, return the string "break" which prevents the result of the function from executing and also disables any default behavior.
def go(event):
if not double_click_enabled:
return "break"
...

How to make window overlay (on top of browser,games exc.) with wxPython

I want to make a simple program (this code is a demo), that will collect system data and display it on top of everything. My goal is to create an overall ping collector for the current biggest internet user.
All I'm asking for is how to make a overlay nothing more.
"""
Hello World, but with more meat.
"""
import wx
class HelloFrame(wx.Frame):
"""
A Frame that says Hello World
"""
def __init__(self, *args, **kw):
# ensure the parent's __init__ is called
super(HelloFrame, self).__init__(*args, **kw)
# create a panel in the frame
pnl = wx.Panel(self)
# and put some text with a larger bold font on it
st = wx.StaticText(pnl, label="Hello World!", pos=(25,25))
font = st.GetFont()
font.PointSize += 10
font = font.Bold()
st.SetFont(font)
# create a menu bar
self.makeMenuBar()
# and a status bar
self.CreateStatusBar()
self.SetStatusText("Welcome to wxPython!")
def makeMenuBar(self):
"""
A menu bar is composed of menus, which are composed of menu items.
This method builds a set of menus and binds handlers to be called
when the menu item is selected.
"""
# Make a file menu with Hello and Exit items
fileMenu = wx.Menu()
# The "\t..." syntax defines an accelerator key that also triggers
# the same event
helloItem = fileMenu.Append(-1, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item")
fileMenu.AppendSeparator()
# When using a stock ID we don't need to specify the menu item's
# label
exitItem = fileMenu.Append(wx.ID_EXIT)
# Now a help menu for the about item
helpMenu = wx.Menu()
aboutItem = helpMenu.Append(wx.ID_ABOUT)
# Make the menu bar and add the two menus to it. The '&' defines
# that the next letter is the "mnemonic" for the menu item. On the
# platforms that support it those letters are underlined and can be
# triggered from the keyboard.
menuBar = wx.MenuBar()
menuBar.Append(fileMenu, "&File")
menuBar.Append(helpMenu, "&Help")
# Give the menu bar to the frame
self.SetMenuBar(menuBar)
# Finally, associate a handler function with the EVT_MENU event for
# each of the menu items. That means that when that menu item is
# activated then the associated handler function will be called.
self.Bind(wx.EVT_MENU, self.OnHello, helloItem)
self.Bind(wx.EVT_MENU, self.OnExit, exitItem)
self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem)
def OnExit(self, event):
"""Close the frame, terminating the application."""
self.Close(True)
def OnHello(self, event):
"""Say hello to the user."""
wx.MessageBox("Hello again from wxPython")
def OnAbout(self, event):
"""Display an About Dialog"""
wx.MessageBox("This is a wxPython Hello World sample",
"About Hello World 2",
wx.OK|wx.ICON_INFORMATION)
if __name__ == '__main__':
# When this module is run (not imported) then create the app, the
# frame, show it, and start the event loop.
app = wx.App()
frm = HelloFrame(None, title='Hello World 2')
frm.Show()
app.MainLoop()
And this is my code so far for the ping collecting "it is still in progress of making and obviously I'll have to modify it a bit + a lot of optimizing.
The topic is on overlay not on this code.
import os
x= os.system('netstat -on > log.txt')
dat = open('log.txt','r')
line = dat.readlines()
dat.close()
list = []
line = line[4:] #removes irrelevant stuff
for x in line:
y = ' '.join(x.split())
if y != '':
list.append(y) #y[1:] tcp irrelevant but i'll keep it
for x in range(len(list)):
list[x] = list[x].split(' ')
top = 0
for x in range(len(list)):
count = 0
for y in range(len(list)):
if list[x][4] == list[y][4]:
count= count+1
if count > top:
top = count
ip = list[x]
ip = ''.join(ip[2].partition(':')[:1])
os.system('ping '+ip+' -n 3 > log.txt') # -n 3 repeat ping 3 times
dat = open('log.txt','r')
ping = dat.readlines()
dat.close()
ping = ping[len(ping)-1:]
print('Ping for ip: '+ip+' '+' '.join(ping[0].split()))
os.system('del log.txt') #useless stuff
input('')
This link is a good tutorial for frame styling/transparent overlays. Here is my favorite code from the tutorial, in which you make a transparent, movable, gray overlay:
import wx
class FancyFrame(wx.Frame):
def __init__(self):
style = ( wx.CLIP_CHILDREN | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR |
wx.NO_BORDER | wx.FRAME_SHAPED )
wx.Frame.__init__(self, None, title='Fancy', style = style)
self.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
self.Bind(wx.EVT_MOTION, self.OnMouse)
self.SetTransparent( 220 )
self.Show(True)
def OnKeyDown(self, event):
"""quit if user press q or Esc"""
if event.GetKeyCode() == 27 or event.GetKeyCode() == ord('Q'): #27 is Esc
self.Close(force=True)
else:
event.Skip()
def OnMouse(self, event):
"""implement dragging"""
if not event.Dragging():
self._dragPos = None
return
self.CaptureMouse()
if not self._dragPos:
self._dragPos = event.GetPosition()
else:
pos = event.GetPosition()
displacement = self._dragPos - pos
self.SetPosition( self.GetPosition() - displacement )
app = wx.App()
f = FancyFrame()
app.MainLoop()
Here is the output of the code:
PS: The code window won't show in the TaskBar

tkinter, print text when hovering over OptionMenu objects

So I got to change the colors as well as change colors while hovering over menu objects created using the OptionMenu in tkinter.
I even have text printing when I hover over the button, but the second I drop down the menu, it won't print anymore.
What am I doing wrong? How can I print when you click to open the OptionMenu and and move around through the selections?
from tkinter import *
import tkinter as tk
OZoneIzotopeSemiWhite = "#c0c4ca"
buttonBackground = "#303336"
buttonforeground = "#cdd0d7"
BACKGROUND2 = "#1e1f21"
class DropDownButton():
def __init__(self, parent, placement, opTions, **kw):
self.parent = parent
self.options = opTions
self.om_variable = tk.StringVar(self.parent)
self.om_variable.set(self.options[0])
self.om_variable.trace('w', self.option_select)
self.om = tk.OptionMenu(self.parent, self.om_variable, *self.options)
self.om["menu"].config(fg=buttonforeground, bg=buttonBackground, activebackground=OZoneIzotopeSemiWhite, activeforeground=BACKGROUND2, borderwidth = 0)
self.om.config(fg=buttonforeground, bg=buttonBackground, activebackground=OZoneIzotopeSemiWhite, activeforeground=BACKGROUND2, bd =0)
self.om.place(x = placement, y = 2)
self.om.bind("<Enter>", self.on_enter)
self.om.bind("<Leave>", self.on_leave)
def on_enter(self, event):
if self.om == self.options[0]:
print ("Hello")
elif self.om_variable.get() == self.options[1]:
print ("Hello 2!")
else:
print("Hell0 3!")
def on_leave(self, enter):
print ("leave")
def option_select(self, *args):
print (self.om_variable.get())
root = tk.Tk()
DropDownButton(root, 55, ['one', 'two', 'three'])
root.mainloop()
You're not doing anything wrong as such, but you might need to alter what you do or your expectations. When a menu is popped up by clicking on a menubutton widget — as created by the option menu code — the mouse pointer is grabbed by the menu that has popped up, and this state continues until you do an action that selects something (or you click or release outside the menu, which cancels). Your styling, which depends on the state of the menubutton, might be noticing this and going into something slightly unexpected to you.
By the way, if you pop up the menu using key bindings, the differing look is actually useful as the focus will also be on the actual popup menu.

Getting tkinter widget values outside main application class?

I have a pygame project which has a main menu - in said menu I have it so that upon clicking the Options button it triggers a Tkinter UI to open. The UI has a OptionMenu widget affecting game speed. How do I retrieve the value of the OptionMenu outside the class I used to create the Tkinter window
Here is a simplified issue:
class GUI(object):
def __init__(self):
import Tk # etc...
# CODE FOR THE PROGRAM WINDOW
defaultSpeed = StringVar(root)
speedMenu = OptionMenu(root, defaultSpeed, 'Slow', 'Normal, 'Fast')
speedMenu.pack()
I know I need defaultSpeed.get() to get the value.
The Pygame menu has this:
click = pygame.mouse.get_pressed()
clicked = click[0] == 1
if "Play" clicked:
startGame(ticks)
if "Options" clicked:
options = GUI()
At this point ^^^ How do I somehow obtain the speed (defaultSpeed.get()) and have it as global variable so that I can use it in the startGame function to affect the number of ticks on clock?
Thinking about it, I'm essentially asking for how to have a global variable defined when initialising a Tkinter class?
I've tried creating a function in GUI() called getSpeed and calling options.getSpeed() but for some reason I still have a logic error that means it's never actually printed/displayed/returned.
I am aware you shouldn't return values when in __init__ - should I just move all my Tkinter app. to a function inside GUI() and leave the __init_ out? surely I could just refrain from initalising it? Would this be better off programmed procedurally over OOP (allowing me to simply call GUI() in the main menu)?
Any help solving is appreciated.
RECAP OF PROBLEM:
Main Menu has 2 options (1 runs game in Pygame, 1 runs Options window in Tkinter)
I need to get the option from the options menu and have it apply to a variable in the game.
EDIT: I was asked to provide a minimal code
I'm currently really busy but here is minimal pseudocode - all you need to do is create the dimensions for the game window and for the menu (they are both 940,500)
import pygame
import time
import math
import tkinter
from tkinter import *
pygame.init()
clock = pygame.tick.Clock()
ticks = 0
#Here is all the game code
#This function is the main game and includes the game loop
def StartGame(ticks):
running = True
myGame1 = teams()
myGame1.startTeam()
#Here is some functions providing the rules of the sport
def updateBall(ticks):
theBall.x += float(theBall.speed) * ticks / 1000
while running:
myGame1.displayPlayers()
updateBall(ticks)
#Calling alot of functions and the game running is here
ticks = clock.tick(30)
pygame.display.flip
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
quit
def game_intro(menu_image):
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
quit
click = pygame.mouse.get_pressed()
clicked = click[0] == 1
if 62+288 > mouse[0] > 62 and 150+28 > mouse[1] > 150:
if clicked:
startGame(ticks)
pass
elif 62+288 > mouse[0] > 62 and 230+30 > mouse[1] > 230:
if clicked:
options = GUI()
class GUI(object):
def __init__(self):
root = self.root = tkinter.Tk
root.geometry('500x400')
root.configure(background = '#ffffff')
speedLabel = tkinter.Message(root, text = 'Game speed: ')
defaultSpeed = StringVar(root)
speedMenu = OptionMenu(root,defaultSpeed, 'Slow', 'Normal', 'Fast')
speedLabel.grid(row = 0, column = 0)
speedMenu.grid(row = 0, column = 1)
game_intro(menu_image)
Before you create defaultSpeed:
global defaultSpeed
Then before you access it:
global defaultSpeed
It basically means that you can access the variable from anywhere after using global.

Disable making another TopLevel if it already exists

I have an Instructions Window asTopLevel in my app. For now it looks like:
def instructions(self):
window = Toplevel(takefocus = True)
window.geometry("200x200")
window.resizable(0, 0)
Label(window, text = "WIP").grid()
So it's part of the main class and I define a command to call when the user presses a button in the top menu or presses F3 a shortcut I defined.
What I need is when that window is once there I want it to take focus rather that opening a new one.
It could look like:
if window == exists:
window.takefocus
else:
do the upper and create it ....
also upon destruction in need to know that it hasbeen destoyed, otherwise I'll be able to open it only once
This seems to work:
def instructions(self):
if self.window == None:
self.window = Toplevel(takefocus = True)
self.window.focus()
self.window.geometry("200x200")
self.window.resizable(0, 0)
Label(self.window, text = "WIP").grid()
self.window.protocol("WM_DELETE_WINDOW", self.windowclosed)
else:
self.window.focus()
def windowclosed(self):
self.window.destroy()
self.window = None

Resources