I have an extremely simple application for a Raspberry Pi. (It's an educational kiosk for a children's museum if anyone cares.) In python, I have an infinite loop in a thread reading a line from a serial port. Based on the input, I display one of 14 different jpg images. I am not putting all the code here, but it's a very bare-bones GDK application. I have an Arduino feeding the serial port the information to cycle through all the images for debug purposes. In response to the input, I do the following:
self.CurrentImage.set_from_file("image.jpg") # the name here is one of 14
Not to anyone's great surprise, this works. But as I let the Arduino hammer at the input, the screen would randomly show a white image and nothing again after. I checked the standard out window and the data was still coming and the images still being read. And when I say random I mean that at some point in the input-and-display process, it stops displaying. There are no errors being reported. Sometimes I might get 4-5 images in sequence before it dies, or I might make it through the list twice. It's simply not deterministic. My mind wandered to thinking maybe I'm not clearing first and having a memory leak. I made the following amendment:
self.CurrentImage.clear()
self.CurrentImage.set_from_file("image.jpg")
The problem persisted. I decided to scrap the method and go for something that didn't involve reloading images. At startup I created a separate GTK Image widget for each file. Then in response to the input data, I did this:
self.CurrentImage.hide()
self.CurrentImage = self.AlphaImage # or one of the other 13 Images I created
self.CurrentImage.show()
The nice thing about this method is that the image displays much faster. The first method had the screen briefly go white as the image was loaded. However, once again, after a random number of image switches, the window goes white. Diagnostic output shows that the loop is happily reading data and selecting images.
In the original version where I loaded images as needed, there was exactly one widget on the window. So it's not possible that another widget is covering it. The second version has an Image widget for each jpg file. If one is covering another, I should still at least see that image.
I'm good at thinking outside the box, but I admit that Linux is a weak area for me. Nothing is occurring to me to try to make this work. I'd whinge that I'm under time pressure here and children will be disappointed... but it was supposed to be done before Christmas and I only got the final art yesterday. That reminds me that there's one final note and the reason I thought my first method was failing: I created temporary graphics of my own that was one word of black text on a white background. Those images displayed without problem until the screensaver kicked in.
I'm open to any suggestion as to how to track this down and fix it.
Thanks to Sylvester, I figured this one out. The problem isn't how I was updating the images, it was where I was doing it. In the thread catching the serial input was not the place to do it. I reduced the thread to simply reading the line, then did the following:
GLib.idle_add( self.updateImage, lineInput )
then in the function updateImage I did the business logic of selecting the correct image and updating. Problem solved.
Related
I'm using:
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER,
0, "picturefile", 0)
To change the wallpaper.
But I'm wondering if there's any simple way to put different wallpapers on each screen.
This feature isn't standard in windows though, but there are external applications like ultramon that do this. Anyone know how that works?
The way I thought it might work if I join the two images together into one and then make that the wallpaper, but then I still need a way to span one image accross both screens.
Also, how could I grab some info about the monitor setup, the resolution of each screen and their placement? Like what you see in the gui display settings in windows, but in numbers.
After joining the images together into a big image, you have to set the wallpaper mode to tiled to make it so the image spans the desktop (otherwise it will restart on each monitor).
Couple of ways to do this:
a) Using IActiveDesktop (which does not require Active Desktop to be used, don't worry). This is nicest as on Win7 the new wallpaper will fade in.
You create an IActiveDesktop / CLSID_ActiveDesktop COM object and then call SetWallpaper, SetWallpaperOptions and finally ApplyChanges. (As I'm not a Python dev, I'm not sure exactly how you access the COM object, sorry.)
OR:
b) Via the registry. This isn't as nice, but works well enough.
Under HKEY_CURRENT_USER\Control Panel\Desktop set:
TileWallpaper to (REG_SZ) 1 (i.e. the string "1" not the number 1)
WallpaperStyle to (REG_SZ) 0 (i.e. the string "0" not the number 0)
Then call SystemParameterInfo(SPI_SETDESKTOPWALLPAPER...) as you do already.
.
By the way, the code I'm looking at, which uses IActiveDesktop and falls back on the registry if that fails, passes SPIF_UPDATEINIFILE | SPIF_SENDCHANGE as the last argument to SystemParameterInfo; you're currently passing 0 which could be wrong.
EnumDisplayMonitors is the Win32 API for getting details on the monitors, including their screen sizes and positions relative to each other.
That API returns its results via a callback function that you have to provide. (It calls it once for each monitor.) I am not a Python developer so I'm not sure how you can call such a function from Python.
A quick Google for "Python EnumWindows" (EnumWindows being a commonly-used API which returns results in the same way) finds people talking about that, and using a Lambda function for the callback, so it looks like it's possible but I'll leave it to someone who knows more about Python.
Note: Remember to cope with monitors that aren't right next to each other or aren't aligned with each other. Your compiled image may need to have blank areas to make things line up right on all the monitors. If you move one of the monitors around and do a PrtScn screenshot of the whole desktop you'll see what I mean in the result.
I am writing an open configurable taskbar using PyQt4, and I want to add a start orb. I want the orb to support the common image format of start orbs, which is usually three 54x54 squares for a 54x162 image.
My program takes those images, cuts them in thirds using PIL, and I try to load them using .setIcon(QIcon(icon)). Unfortunately, this isn't working. The image is loaded, calling .show() displays the image perfectly.
For various reasons, I did not choose style sheets, including that I would have trouble loading the cut images. Instead, (as the code shows) I had the QPushButton change icons on hover, press, and release. None of them work. Not even the default image.
My code is on this github. Note the warning in the readme! The program quite literally replaces (and removes) the taskbar (but you can get it back).
tl;dr
I have the code (see link below). It won't load using .setIcon(), and I don't know why. I thought it would work, used ImageQt, but no.
EDIT:Unfortunately, going from a PIL object to a Imagqt object to a QImage didn't solve the problem.
EDIT2: as #Trilarion requeted here is a link to a gist of the slimmed down code: https://gist.github.com/IronManMark20/85b00104c9bb52b78add
I have a file containing thus far some 1800 jpegs (it will grow) which I have to search manually for specific features. This requires that I enter a code (1 or 0) to say whether or not the features that I am looking for exist.
Because the features are difficult to define, the images of low quality and as far as we are aware no non-deterministic approach exists to deal with this satisfactorily it has to be coded.
The idea is to open the large_file containing the jpegs, open each of them in a new window one-by-one (so that I can see them), read in data from the screen and then close the new window.
Roughly this looks something like this:
large_file = open (xxxxxx, rb) # contains info identifying jpeg
for jpeg in large_file: # 1800 items now more later
open jpeg in separate window
does image meet the criterion?: # Enter 1 or 0 (say) at console
if (1 or 0):
close window and move to next image
else:
go back and ask for sensible input
large_file.close()
I am running Kubuntu 14.04 with lightdm as the display manager and Python 2.7.6. Browsing Stackoverflow doesn't really get me what I need.
Implementing using Image cause problems because I am not using xv, but lightdm. Several strategies have not worked properly. Clearly the core issue is spawning the new window and then closing it.
Any suggestions? In an ideal world I would prefer not to have to close images manually...
Many thanks
I am writing a program for audio-visual experiments, which will present a pre-generated list of audio-only and video-with-audio stimuli to experiment subjects. I have decided to use PyQT and Phonon for this, despite the fact that I'm fairly new to writing QT-based programs (and GUI programming in general).
The issue I'm having is that, when the previous file played was video (.mov in this case), and the current file is audio-only (.wav file), the image from the last frame of the video file remains on the screen while the audio file is playing. The video image remains until the next .mov file rolls around in the stimulus list.
Is there a way to clear the Phonon screen, in order to show just an empty black screen while the audio-only files are playing? I've done a fair bit of poking around with Google, and though this question has been asked by a number of people on different forums, it seems to have gone unanswered.
Any suggestions will be greatly appreciated!
This seems to be a bug, or missing feature, and it's hard to come up with a good workaround.
One somewhat hacky solution is to force a resize of the video widget:
size = self.video.size()
self.video.resize(0, 0)
self.video.resize(size)
but I wouldn't bet on this working on all platforms.
A more reliable workaround would be to put the video-widget inside a container widget with a black background, and then simply hide/show the video-widget when stopping/starting the media.
I'm developing a python plugin for Rhythmbox - this contains a GtkScrolledWindow with a child which is a GtkIconView. The IconView is fed from a Gtk.TreeModel.
It looks like this:
Currently - and somewhat inefficient, every icon is drawn for every row in the tree-model - each icon is a GdkPixbuf from a file. If you have thousands of rows, it can take quite a while for the whole iconview to be fully updated with every picture icon.
What I am trying to achieve is to only update the icons that are in the current drawing area - when the user scrolls and releases the scrollbar (or navigates via the keyboard), the icons in the new drawing area should be updated with relevant pictures.
N.B. - the tree-model would be fully populated at this point - only the icons would not have been loaded.
This is not really my area of expertise - I'm looking for pointers for the best approach I should use to achieve the above.
Specifically - which Gtk+3 drawing-area signal (or signals) can be exposed (Gtk.ScrolledWindow / Gtk.IconView ?) to write python code to calculate what icons should be updated?
You should profile you application to see what takes time.
Is that loading the images ? If it is, then loading a default image and adding it everywhere in your view would be quick enough, as you'd load only one image. You'd then load and update the images on-demand using idle_add, based on the images that should appear in the viewport.
If what takes times is adding the images to the model, then you'd need to do the adding on-demand, by checking what is visible on the viewport in your idle_add callback.
If both are slow, you'd need a mix of both solutions: loading and adding on-demand.
Think also about the proxy design pattern that can be useful to create a fake cover object that will load in the background, and contain the loading policy.
For the signals, your GtkIconView widget implements GtkScrollable, which explains how to implement scrolling. You'd set your vertical adjustment and check when it has changed by connecting to its value-changed signal. This would mean the user scrolled up or down, and you'd need to fire up a timer with timeout_add. If after a short timeout (between 0.5 and 1s I think, but needs testing), the adjustment hasn't changed, this means the user stopped scrolling, and you can update what is displayed. Otherwise, it would be updated during the scrolling, slowing everything down. You then just need to figure out how to find which items appear in the viewport, to update their cover.
I've never done this before though, but I know GTK a bit and just tried to figure out how it would be done, so read that with a bit of caution. Anyway, the answer to reactivity is "on-demand".
But on the other hand if you have to scroll completely down, you would have to wait for every page to be build. So i guess you should better consider the idle_add function of the event loop.
This way your screen doesn't lock up and your pc doesn't have to wait for the user to load the view page for page. Win-Win for you and your application. ;-)