How can I get consistent behavior on my wxPython StyledTextControl? - python

I am having a problem with wxPython. I am attempting to have a scrollable window without a visible scroll bar. I still want to be able to use the mouse wheel to scroll as well as use the keyboard shortcuts that I have written.
I have the following simplified code:
import wx
import wx.stc
app = wx.App(0)
frame = wx.Frame(None, wx.ID_ANY, "Sample Scroll pane")
textViewer = wx.stc.StyledTextCtrl(frame, wx.ID_ANY)
textViewer.Text = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22"
textViewer.SetUseVerticalScrollBar(False)
textViewer.ScrollLines(1)
frame.Show()
app.MainLoop()
I am using the "ScrollLines" function to scroll my text programatically. On a windows machine this works as expected and scrolls down one line. However, on Ubuntu, the text does not scroll if the "SetUseVerticalScrollBar" is false.
How can I hide my scrollbar while maintaining it's functionality in a cross platform manner?

ScrollToLine seems to work consistently on Windows and Linux, so you could replace the ScrollLines call with something like this:
first = textViewer.GetFirstVisibleLine()
textViewer.ScrollToLine(first + n)
where n is the number of lines to scroll down.

Related

wxpython toolbar not shown in os x

I have a python script for GUI using wxpython. It works perfectly fine in Windows, however, when I run the script in OS X, the toolbar is now shown (I installed wxpython from its official website and used the cocoa version, and I am using OS X 10.10 and python 2.7). Following is the part of the code regarding the toolbar:
self.toolBar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_FLAT|wx.TB_DOCKABLE)
self.myChoice = ComboBoxWithHelp(self.toolBar, wx.NewId(), size=(200, -1), value=..., choices=..., style=wx.CB_DROPDOWN,)
self.toolBar.AddControl(self.myChoice)
iconname = 'icons/new.png'
self.toolBar.AddSimpleTool(1, wx.Image(iconname, wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'New', 'New')
...
self.toolBar.Realize()
self.SetToolBar(self.toolBar)
Nothing is shown below the menu bar, however the space is left there. Did I installed the wxpython wrongly or use the function wrongly?
By the way, the above code also works for Ubuntu.
What is self in this code? Toolbars are a little different on OSX, and and can be a bit tricky, so there may be some issues if self is not a wx.Frame or a class derived from wx.Frame. This is because the native toolbars are actually part of the frame rather than an independent widget. It should be switching to a non-native toolbar if the parent is not the frame, but then you'll need to manage its size and layout yourself.
If self is already the frame then you may want to try not specifying the style flags and let it just use the default style, or you can try creating the toolbar like this instead and let the frame create it:
self.toolBar = self.CreateToolBar()

After adding "primary toolbar" style class to a gtk.Builder object, gtk.ToolButtons in toolbar are not primary-themed

I've been trying to get my toolbar to look like the standard toolbars in stock Ubuntu apps, and it works to an extent, except the buttons in the toolbar do not have the correct theming applied to them. The text is colored for the default toolbar, and on hover the buttons are an ugly tan color instead of getting darker grey as they do in the standard Ubuntu apps.
In other words I'm getting this:
Instead of this:
(I don't have enough rep to post images directly)
I've been using the following method to change the toolbar style, since Glade doesn't seem to have an option to change it itself:
self.bd = Gtk.Builder()
self.bd.add_from_file("builderfile.glade")
self.bd.connect_signals(self)
...
toolb = self.bd.get_object("toolbar")
toolb_style = toolb.get_style_context()
toolb_style.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
This works to the extent that the toolbar is now darkened, but the buttons are incorrectly themed. I tried adding buttons to the toolbar manually after setting the STYLE_CLASS_PRIMARY_TOOLBAR instead of using Gtk.Builder() but they weren't the right color either.
I suppose manually creating a toolbar and filling out all the information might work, but it would be nice to be able to use Glade for the design.
I'm writing this answer here since it's a solution, but it's not ideal because it doesn't use Glade and it's kind of messy. I'll have to wait until a new build of Glade gets into Ubuntu, since apparently the feature has been added upstream.
The solution I eventually used was just to do all the toolbar creation in standard GTK and python, and then add it to an empty Gtk.Box defined in Glade. Like this:
bd = Gtk.Builder()
bd.add_from_file("gladefile.glade")
...
button1 = Gtk.ToolButton(stock_id=Gtk.STOCK_ADD, ...)
button2 = Gtk.ToolButton(...)
toolbar = Gtk.Toolbar()
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
toolbar.insert(button1, 0)
toolbar.insert(button2, 1)
toolbar.show_all()
bd.get_object("toolbar_slot").pack_start(toolbar, False, True, 0)

wxPython: Exit Fullscreen

To display a wxPython window in full screen mode you use:
ShowFullScreen(True)
How do you get out of full screen though? I've tried the obvious way:
ShowFullScreen(True)
sleep(5)
ShowFullScreen(False)
This doesn't work though. When I run the script, nothing appears. After 5 seconds a window roughly 200x250 appears in the top-left corner of the screen, without anything inside of it. It doesn't appear to have any borders either.
If I change this to
showFullScreen(True)
then I get stuck with a full screen window that I have to use Alt + F2 -> xkill to get out of.
It looks like you need to Show() the window first. (According to the documentation, you shouldn't have to. Maybe this is a bug.) I tested on Mac OS X and Windows - they both exhibit issues if you don't call Show() first.
Also note that you shouldn't sleep in the main GUI thread. You'll hang the UI. Using CallLater is one potential solution, as shown in my example.
Working example:
import wx
def main():
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, 'Full Screen Test')
frame.Show()
frame.ShowFullScreen(True)
wx.CallLater(5000, frame.ShowFullScreen, False)
app.MainLoop()
if __name__ == '__main__':
main()
The documentation for ShowFullScreen reads:
ShowFullScreen(show, style=wx.FULLSCREEN_ALL)
Depending on the value of show parameter the window is either shown full screen or restored to its normal state.
Parameters:
show (bool)
style (long): is a bit list containing some or all of the following values, which indicate what elements of the window to hide in full-screen mode:
wx.FULLSCREEN_NOMENUBAR
wx.FULLSCREEN_NOTOOLBAR
wx.FULLSCREEN_NOSTATUSBAR
wx.FULLSCREEN_NOBORDER
wx.FULLSCREEN_NOCAPTION
wx.FULLSCREEN_ALL (all of the above)
So put your Full Screen toggle event/s in a Menu and start full screen mode with:
self.window.ShowFullScreen(True, style=(wx.FULLSCREEN_NOTOOLBAR | wx.FULLSCREEN_NOSTATUSBAR |wx.FULLSCREEN_NOBORDER |wx.FULLSCREEN_NOCAPTION))
Note that I omitted wx.FULLSCREEN_NOMENUBAR, in this way you will still be able to access the menu to turn full screen mode off again.

Prevent scrollbars from showing up when placing a drawing area inside a scrolled window

I'm working on a project using Python and pyGTK. I have a window whose only purpose is showing an image. Unless the image is too big to fit the screen, the window should show no scrollbars by default.
So what I do is something like this:
window = gtk.Window()
window.resize(image.size[0], image.size[1])
scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_NONE)
area = gtk.DrawingArea()
area.set_size_request(image.size[0], image.size[1])
window.add(scrolled)
scrolled.add_with_viewport(area)
area.show()
scrolled.show()
window.show()
But it doesn't quite work. The resulting window is a little too small, and thus, scrollbars show up.
For it to work, I have to thange the second line to this:
window.resize(image.size[0] + 2, image.size[1] + 2)
But that is ugly, and it doesn't work under all systems. In my Windows box I have to use + 3.
What can I do to make sure the window is big enough for the image?
I figured it out :).
If you put a DrawingArea inside a ScrolledWindow, things just won't work as they should. Instead, you have to put the DrawingArea in a Viewport, and the Viewport in the ScrolledWindow. gtk.ScrolledWindow provides a method, gtk.ScrolledWindow.add_with_viewport, that does this automatically, for convenience's sake. The problem is the viewport generated by that method has a border by default, and that border varies in width depending on the system. Also, there's no way (that I know of) of accessing the generated Viewport (edit: you can use scrolled.get_child()) to get rid of the border. The solution is simple: you have to manually create the Viewport.
window = gtk.Window()
window.resize(image.size[0], image.size[1])
scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_NONE)
viewport = gtk.Viewport()
viewport.set_shadow_type(gtk.SHADOW_NONE) // Get rid of the border.
area = gtk.DrawingArea()
area.set_size_request(image.size[0], image.size[1])
window.add(scrolled)
scrolled.add(viewport)
viewport.add(area)
viewport.show()
area.show()
scrolled.show()
window.show()
It worked like a charm on Arch (GNOME 3), Windows XP, Windows 7 and Ubuntu (Unity).

Controling button/hbox sizes in gtk

I am writing an app in python using getk and I've come across a problem. I am using an hbox to hold the buttons that go on my tool bar (new, open, save, etc) but the hbox seems to be expanding to take up a particular portion of the screen and the buttons are doing so as well making them really tall and ugly. How do I get them to stay at adecent size? I have already tried setting the expand and fill values to false and I can't find any methods to control the size of ether a button or an hbox. Here is the code for my new button:
img = gtk.Image()
img.set_from_stock(gtk.STOCK_NEW,gtk.ICON_SIZE_SMALL_TOOLBAR)
newButt = gtk.Button()
newButt.set_image(img)
newButt.show()
self.hBox4.pack_start(newButt, False, False, 0)
You need to contain the entire HBox in a VBox, as follows:
main = gtk.VBox(False)
...
main.pack_start(self.hbox4, False)
The reason for this is that gtk allows for window resizing, so it doesn't allocate fixed heights and widths. By using a VBox, you are telling Gtk that I want the HBox to take up just as much space as it needs at the top of my window.
Hope that helps.
Child widgets will assume the allocation size that they parent widgets can give. You should set the size of the hbox or the button.
See here the size_request method of PyGTK to get more information.

Categories

Resources