How To Make Mini Example For DrawingArea Display Something - python

I've written a mini example for DrawingArea which, when started, displays nothing. If I insert a raw_input() just for waiting for a keyboard press at a specific place, it functions, so this is a workaround. Here's the code:
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
R = 300
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_default_size(R, R)
drawing_area = gtk.DrawingArea()
window.add(drawing_area)
window.show_all()
gc = drawing_area.get_style().fg_gc[gtk.STATE_NORMAL]
if 0:
raw_input()
drawing_area.window.draw_line(gc, R/10, R/10, R*9/10, R*9/10)
raw_input()
This version doesn't display the drawn line in the opening window; upon pressing enter in the shell, it will just terminate (and remove the window). But if I enable the raw_input() at the if 0: block, it waits twice for an enter in the shell and between the two enters it will display the drawn line (so in general the code works, it seems to be just a weird refresh problem).
I also tried to flush the event queue of GTK using this snippet:
while gtk.events_pending(): # drain the event pipe
gtk.main_iteration()
I inserted it at various places, always to no avail.
I also tried the usual gtk.main() as the last command in the script (of course). But it also didn't help.
How do I do this correctly and why is that raw_input() having that strange side-effect?

You should connect to your drawing area's expose-event signal. That is the only place that you should try to draw on the drawing area; the reason for this is that anything you draw is erased again when the window is minimized or another window moves over it. However, the expose event always happens at the right time so you can keep the drawing up-to-date whenever it is needed.
Like this:
def on_drawing_area_expose(drawing_area, event, data=None):
# ... do your drawing here ...
drawing_area.connect('expose-event', on_drawing_area_expose)
Also check out drawing with Cairo, which is the preferred and more flexible way. Here is a tutorial.

Related

pygame fullscreen on second monitor [duplicate]

I am using pygame to program a simple behavioral test. I'm running it on my macbook pro and have almost all the functionality working. However, during testing I'll have a second, external monitor that the subject sees and the laptop monitor. I'd like to have the game so up fullscreen on the external monitor and not on the laptop's monitor so that I can monitor performance. Currently, the start of the file looks something like:
#! /usr/bin/env python2.6
import pygame
import sys
stdscr = curses.initscr()
pygame.init()
screen = pygame.display.set_mode((1900, 1100), pygame.RESIZABLE)
I was thinking of starting the game in a resizable screen, but that OS X has problems resizing the window.
Pygame doesn't support two displays in a single pygame process(yet). See the question here and developer answer immediately after, where he says
Once SDL 1.3 is finished then pygame will get support for using multiple windows in the same process.
So, your options are:
Use multiple processes. Two pygame instances, each maximized on its own screen, communicating back and forth (you could use any of: the very cool python multiprocessing module, local TCP, pipes, writing/reading files, etc)
Set the same resolution on both of your displays, and create a large (wide) window that spans them with your information on one half and the user display on the other. Then manually place the window so that the user side is on their screen and yours is on the laptop screen. It's hacky, but might a better use of your time than engineering a better solution ("If it's studpid and it works, it ain't stupid" ;).
Use pyglet, which is similar to pygame and supports full screen windows: pyglet.window.Window(fullscreen=True, screens[1])
Good luck.
I do not know if you can do this in OS X, but this is worth mentioning for the Windows users out there, if you just want to have your program to run full screen on the second screen and you are on windows, just set the other screen as the main one.
The setting can be found under Rearrange Your Displays in settings.
So far for me anything that I can run on my main display can run this way, no need to change your code.
I did something silly but it works.
i get the number of monitors with get_monitors()
than i use SDL to change the pygame window's display position by adding to it the width of the smallest screen, to be sure that the window will be positionned in the second monitor.
from screeninfo import get_monitors
numberOfmonitors = 0
smallScreenWidth = 9999
for monitor in get_monitors():
#getting the smallest screen width
smallScreenWidth = min(smallScreenWidth, monitor.width)
numberOfmonitors += 1
if numberOfmonitors > 1:
x = smallScreenWidth
y = 0
#this will position the pygame window in the second monitor
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
#you can check with a small window
#screen = pygame.display.set_mode((100,100))
#or go full screen in second monitor
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
#if you want to do other tasks on the laptop (first monitor) while the pygame window is being displayed on the second monitor, you shoudn't use fullscreen but instead get the second monitor's width and heigh using monitor.width and monitor.height, and set the display mode like
screen = pygame.display.set_mode((width,height))
display = pyglet.canvas.get_display()
display = display.get_screens()
win = pyglet.window.Window(screen=display[1])
------------------------------------------------------
screen=display[Номер монитора]
------------------------------------------------------
display = pyglet.canvas.get_display()
display = display.get_screens()
print(display) # Все мониторы которые есть

TKinter window not responding in Python

I'll get straight to the point. My TKinter window opens, but crashes immediately, displaying the (not responding) message. Here's my code:
from graphics import graphics
gui = graphics(500, 500, 'number')
text = 'no'
while text != 'yes':
gui.clear() # Clears window
gui.text(0, 0, text) # Displays text on window
gui.update_frame(1) # Updates window
text = input("Insert text: ") # Updates text object
Now you might be wondering what the graphics class is. Long story short, it's a python file that our teacher provided for us as an alternative for using TKinter directly, even though the file itself uses TKinter. Here are the relavant functions from that file:
def update(self):
""" Does an idle task update and regular update.
"""
self.primary.update_idletasks()
self.primary.update()
def frame_space(self, frame_rate):
""" Sleeps for a time that corresponds to the provided frame rate.
"""
sleep_ms = 1.0 / float(frame_rate)
time.sleep(sleep_ms)
# This is the update frame function in the other file.
def update_frame(self, frame_rate):
""" Updates and sleeps.
This should be called at the end of each iteration of a users draw loop.
"""
self.update()
self.frame_space(frame_rate)
Now, I should mention that I am using PyCharm as my IDE, and that everyone else that is using the Mu IDE is not facing this issue. Are there any possible edits to the update_frame() function that can solve this problem for the PyCharm IDE?

time .sleep() taking place at incorrect order in commands; always at the beginning of the function

The code below is a stripped down version (for clarity reasons) of a small application I am working on; an application for spelling words for children.
The problem
The problem I am having is in the function flash_correct(); its purpose is to show a word for 5 seconds, then hide again.
I must have a silly blind spot, but no matter where I put the time.sleep(5), the function starts with the break of 5 seconds, while the entry: self.entry2 never shows up:
Without the time.sleep(5) however, it shows up correctly:
Where is my blind spot?
The (stripped down) code:
#!/usr/bin/env python3
from gi.repository import Gtk, Pango, Gdk
import subprocess
import time
class InterFace(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Woorden raden")
maingrid = Gtk.Grid()
self.add(maingrid)
maingrid.set_border_width(10)
self.entry2 = Gtk.Entry()
self.entry2.set_size_request(500,60)
self.entry2.set_child_visible(False)
self.entry2.modify_font(Pango.FontDescription('Ubuntu 30'))
maingrid.attach(self.entry2, 0, 4, 4, 1)
quitbutton = Gtk.Button("Stop", use_underline=True)
quitbutton.modify_font(Pango.FontDescription('Ubuntu 20'))
quitbutton.connect("clicked", self.on_close_clicked)
maingrid.attach(quitbutton, 3, 7, 1, 1)
showword_button = Gtk.Button("↺", use_underline=True)
showword_button.modify_font(Pango.FontDescription('Ubuntu 25'))
showword_button.connect("clicked", self.flash_correct)
showword_button.set_size_request(60,20)
maingrid.attach(showword_button, 0, 6, 1, 1)
def flash_correct(self, button):
# the time.sleep(5) seems to take place at the beginning
# no matter in which order I set the commands
self.entry2.set_text("Monkey")
self.entry2.set_child_visible(True)
time.sleep(5)
self.entry2.set_child_visible(False)
def on_close_clicked(self, button):
Gtk.main_quit()
window = InterFace()
window.connect("delete-event", Gtk.main_quit)
window.set_default_size(330, 330)
window.set_resizable(False)
window.show_all()
Gtk.main()
You can use time.time to hide for roughly 5 seconds calling Gtk.main_iteration() in the loop to avoid your app becoming unresponsive.
def hide(self, time_lapse):
start = time.time()
end = start + time_lapse
while end > time.time():
Gtk.main_iteration()
def flash_correct(self, button):
# the time.sleep(5) seems to take place at the beginning
# no matter in which order I set the commands
self.entry2.set_text("Monkey")
self.entry2.set_child_visible(True)
self.hide(5)
self.entry2.set_child_visible(False)
There is a good explanation in the pygtk faq 7. How can I force updates to the application windows during a long callback or other internal operation?
If you have a long-running callback or internal operation that tries to modify the application windows incrementally during its execution, you will notice that this doesn't happen; the windows of your app freeze for the duration.
This is by design: all gtk events (including window refreshing and updates) are handled in the mainloop, and while your application or callback code is running the mainloop can't handle window update events. Therefore nothing will happen in the application windows.
The trick here is to realize where your operation can take a while to return, or where it is dynamically changing the window contents, and add a code fragment like this wherever you want an update forced out:
while gtk.events_pending():
gtk.main_iteration(False)
This tells gtk to process any window events that have been left pending. If your handler has a long loop, for instance, inserting this snippet as part of the loop will avoid it hanging the window till the callback has finished.
More eloquently, in the words of the great Malcolm Tredinnick, 'this requires using what should be called "Secret Technique #1 For Making Your Application Look Responsive"(tm):
Adding while gtk.events_pending(): may be no harm also.
It would be better to use a timer that integrates with the main loop, rather than busy-waiting until the time has elapsed. Luckily there is just such a facility in GLib:
def flash_correct(self, button):
self.entry2.set_text("Monkey")
self.entry2.set_child_visible(True)
GLib.timeout_add_seconds(5, self.flash_end)
def flash_end(self):
self.entry2.set_child_visible(False)
return GLib.SOURCE_REMOVE

PySide / Python GUI freezes

I'm currently writing a GUI for rvplayer that shall enable artists to automatically render dailies with slate and burn-in information. The GUI is written with PySide and scripted in Python 2.7. My problem is that upon calling my process and updating my QProgressBar with the stdout the GUI freezes. I know that this is a common problem and that it can probably be solved with processEvents() somehow, but I know far too little about threading and process loops to get my head around this issue. Since my code is a little lengthy already, here's the part that causes the issue:
def rv(self, args):
p = subprocess.Popen(["C:/Program Files/Tweak/RV-4.0.10-64/bin/rvio_hw.exe"]+[x for x in args], stdout=subprocess.PIPE)
while True:
line = p.stdout.readline()
if line != "":
progressStr=re.search(r"([0-9]+.[0-9]+%)", line.rstrip())
if progressStr == None:
print line.rstrip()
else:
progressInt=int(float(re.sub("[^0123456789\.]", "", progressStr.group())))
self.prog_QProgressBar.setValue(progressInt)
print progressStr.group()
else:
break
and here is the part that starts my QApplication:
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
finalForm = MainWindow()
finalForm.show()
sys.exit(app.exec_())
I'm calling the function rv upon pressing a button and although the progress bar keeps updating normally, the window starts to get nonresponsive after some time. I do not understand at which point I could use app.processEvents() to tell my QApplication to run the process in a separate thread or in the background.
Since it looks like you're not using threads, it may be that all that's required is to call processEvents after updating the progress bar, like this:
self.prog_QProgressBar.setValue(progressInt)
QtGui.qApp.processEvents()
However, the effectiveness of this may depend on how long it takes the process to produce the output. All that the processEvents call does is to immediately handle any pending events (e.g. widget painting, mouse clicks, etc) that are currently in the application's event queue. In between those calls, the GUI will continue to freeze (i.e. the executing code is not run in a separate thread or in the background, as you suggested). So the extent to which this technique can keep the GUI responsive depends on how frequently processEvents can be called within the rv() method.
The issue is that it's not as if your app is frozen, but Windows thinks that the app is frozen as it's ignoring events (mouse over, click etc etc), so Windows, in its wisdom, gives you that dialogue.
You need to start the thread off after the show() and then run the processEvents function, and obviously only call sys.exit once your thread has finished.

turtle onclick() method not working as it should

The following code creates a window in which a python turtle follows wherever your mouse goes. However, it draws indescriminately of whether the user is clicking to draw or not. My code is the following:
Note: You must have pythonwin installed in order for this program to work properly
import turtle, win32api
while True:
# turtle.penup()
user = win32api.GetCursorPos()
mousepos = [user[0]-510,-1*(user[1])+ 410]
turtle.goto(mousepos)
turtle.onclick(turtle.pendown())
In theory, this would only draw when the user is pressing and holding the mouse, but it doesn't work in practice. The commented code will simply cause it to not draw at all. Any advice?
turtle.onclick(turtle.pendown())
Here, you are calling pendown(), which returns probably None; then you're passing this None to onclick(). It probably means "do nothing on a click". That's probably not what you want.
According to #Gibby's comment, you want:
def clicked(*args): # args ignored
turtle.pendown()
turtle.onclick(clicked)

Categories