EDIT: Solution found and shown in code below.
Python noob here. I usually like to find answers myself, but I'm striking out on this one.
I simply want to set the directory the user starts in when FileChooser opens (rather than have the Python working directory).
This seems like such a simple thing and a common need, I am surprised and frustrated that I could not find anything in Glade (which I used to create the FileChooser), nor in any online GTK documentation.
So... how can this be done?
As mentioned I built the xml file with Glade and loaded it with gtk.builder.
Thanks much for any help
CODE WITH (A) SOLUTION
def GetFile():
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
chosenfile = None
class Handler:
def on_destroy(self, *args):
Gtk.main_quit()
def on_OK_clicked(self, *args):
nonlocal chosenfile
chosenfile = window.get_filename()
Gtk.main_quit()
def on_cancel_clicked(self, *args):
nonlocal chosenfile
chosenfile = "CANCELLED"
Gtk.main_quit()
builder = Gtk.Builder()
builder.add_from_file("mod_FileChoose.glade")
builder.connect_signals(Handler())
window = builder.get_object("FileSelector")
#HERE IS THE LINE IN QUESTION
Gtk.FileChooser.set_current_folder(window, "/home/")
window.show_all()
Gtk.main()
return chosenfile
I should add that in GTK API source where I found this, it states:
"In general, you should not use this function. See the section on setting up a file chooser dialog[gtkfilechooserdialog-setting-up] for the rationale behind this."
So far I have not found the setting-up section with rationale for not using or better approach.
Source: gtk API ref
It seems to be okay to use the set_current_folder method as to the mentioned "setup section" that can be found here:
Note that old versions of the file chooser’s documentation suggested using gtk_file_chooser_set_current_folder() in various situations, with the intention of letting the application suggest a reasonable default folder. This is no longer considered to be a good policy, as now the file chooser is able to make good suggestions on its own. In general, you should only cause the file chooser to show a specific folder when it is appropriate to use gtk_file_chooser_set_filename(), i.e. when you are doing a Save As command and you already have a file saved somewhere.
Addtional info: to look up docs, I use the DevHelp tool on Linux. Most Gtk docs (for python) for it can be found on this github repo. The offical online docs for Gtk3 should be these.
Related
I am beginning to work on a program in which i want multilingual support, but since it is pretty modular (and i want it to be even more in the future), a language change means "destroy what you had of interface and build again with the content which language modules have". (You can see the source as of now on GitHub)
This full-modular approach may give many problems, but i still want it, and so the problem is: Whenever i destroy the widgets i had, until i am alone with the raw Gtk.Window itself, i am not able to assign once again widgets to it. They won't get displayed at all, sometimes silently, sometimes with errors depending on my approach.
Lets suppose the class window, which inherits from a Gtk.Window.
This class is the raw window, and i assign to it a Gtk.Box -
self.interface.
self.interface itself, has two Gtk.Box's, one sidebar and one stack of contents.
To rebuild i tried to:
Change the language variable
Use the method destroy on self.interface, which removes the widget and its child's.
Reuse the function to build the widgets stack on top of self.interface
Re-add self.interface to self (window).
This approach returns:
g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Gtk.main()
Pointing to the .show_all() method in this file.
I've already tried to leave interface without using .destroy on it, applying only on its child's, and then creating them again over it, but didn't worked. The window was left blank with no error at all.
The code i am trying right now is:
#Remember, self is a Gtk.Window()
def __init__(self):
[...]
self.interface = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.stack = None
self.add(interface)
self.build_interface()
def build_interface(self):
self.interface.pack_start(
self.create_side_navigation(
self.interface_data["menu"][self.language]["name"])
, False, False, 0
)
self.stack = self.create_content_stack(self.interface_data["menu"][self.language])
self.interface.pack_start(self.stack, True, True, 0)
###Code to rebuild(this is a question dialog):
if response == Gtk.ResponseType.OK:
self.language = self.new_language["Index"]
self.new_language = None
self.stack.destroy()
self.interface.destroy()
self.interface = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.build_interface()
self.add(self.interface)
This code will cause the previously told "g_object_unref" error.
What is causing this? Why can't i add anything once deleted?
Feel free to clone the repo and try, the code is well commented(yet i am not sure if poorly written, i am a python newbie) and its quite easy to understand where is the problematic part. Its not too big.
PS: It should need GTK+3.12 because of the popovers.
As a GTK Dev showed to me, GTK has by default all the widgets invisible.
The error was caused in the line which declared the whole interface visibility (windowclass.show_all()), but since the interface changed since when it was applied, it threw that warning.
He pointed me to .remove() instead of .destroy(), and to set .show_all() to the new elements after set up.
The next commit(or the following) on that git, has the solution.
The best way to be multilingual is to keep your widgets the same and merely change the text of labels and titles. This can be done without disturbing the overall setup. For example:
s='Stop'
if lang=='fr': s='Arret'
...
somelabel.set_label(s)
I'm writing a text-based hex viewer for fun and usefulness(I intend to add syntax highlighting for many different filetypes), and am wondering if there are any curses toolkits I could use.
I will probably write something myself anyway as to familiarize myself with the way gui toolkits work, but it would be nice to know of useful libraries for future reference for myself and others.
Urwid is the best library to work with curses and python that I know.
Altenatively, you might find also interesting snack (newt-based library).
For more information, please have a look at this question.
npyscreen
Npyscreen is a Python widget library and application framework for programming terminal or console applications. It is built on top of ncurses, which is part of the standard library.
The focus of this library is to provide a rapid way to develop console applications. In general, adding a control to the screen requires only one line of code.
This framework should be powerful enough to create everything from quick, simple programs to complex, multi-screen applications.
#!/usr/bin/env python
# encoding: utf-8
import npyscreen
class TestApp(npyscreen.NPSApp):
def main(self):
# These lines create the form and populate it with widgets.
# A fairly complex screen in only 8 or so lines of code - a line for each control.
F = npyscreen.Form(name = "Welcome to Npyscreen",)
t = F.add(npyscreen.TitleText, name = "Text:",)
fn = F.add(npyscreen.TitleFilename, name = "Filename:")
fn2 = F.add(npyscreen.TitleFilenameCombo, name="Filename2:")
dt = F.add(npyscreen.TitleDateCombo, name = "Date:")
s = F.add(npyscreen.TitleSlider, out_of=12, name = "Slider")
ml = F.add(npyscreen.MultiLineEdit,
value = """try typing here!\nMutiline text, press ^R to reformat.\n""",
max_height=5, rely=9)
ms = F.add(npyscreen.TitleSelectOne, max_height=4, value = [1,], name="Pick One",
values = ["Option1","Option2","Option3"], scroll_exit=True)
ms2= F.add(npyscreen.TitleMultiSelect, max_height =-2, value = [1,], name="Pick Several",
values = ["Option1","Option2","Option3"], scroll_exit=True)
# This lets the user interact with the Form.
F.edit()
print(ms.get_selected_objects())
if __name__ == "__main__":
App = TestApp()
App.run()
On GitHub there is a free to use, study, modify and re-distribute High Level GUI library, at "https://github.com/rigordo959/tsWxGTUI_PyVx_Repository".
It is implemented in Python 2x & 3x using the "curses" Low Level GUI package.
Your application programs can be programmed using a character-mode subset of the pixel-mode "wxPython" High Level GUI API. It supports displays with keyboard and mouse input and various terminal emulators including the color xterms (8-color with 64-color pairs and 16-color with 256-color pairs) and non-color vt100/vt220.
I'd like to have my application display an icon in OSX menu bar (top of screen where Growl sits). How would I do this using Python? (I understand this is not possible using wxPython but I am not after a wxPython specific solution).
Thanks!
An implementation of this may be found at:
https://web.archive.org/web/20080709014939/http://the.taoofmac.com/space/blog/2007/04/22/1745
http://the.taoofmac.com/space/blog/2007/04/22/1745
The API for displaying icons in the OS X menubar is called NSStatusItem. It's going to be difficult or impossible to use from a wxPython application, though -- you will probably have to write your application using PyObjC to use it effectively.
The rumps package makes this very easy. Here's an example from rumps's README:
import rumps
class AwesomeStatusBarApp(rumps.App):
#rumps.clicked("Preferences")
def prefs(self, _):
rumps.alert("jk! no preferences available!")
#rumps.clicked("Silly button")
def onoff(self, sender):
sender.state = not sender.state
#rumps.clicked("Say hi")
def sayhi(self, _):
rumps.notification("Awesome title", "amazing subtitle", "hi!!1")
if __name__ == "__main__":
AwesomeStatusBarApp("Awesome App").run()
Ive tried the gtk method, but it is very slow and doesn't work for a 'large' image (120 kb)
import pygtk
pygtk.require('2.0')
import gtk
import os
def copy_image(f):
assert os.path.exists(f), "file does not exist"
clipboard = gtk.clipboard_get()
img = gtk.Image()
img.set_from_file(f)
clipboard.set_image(img.get_pixbuf())
clipboard.store()
Ive tried xclip and it only does text, so what other options are there? What does ubuntu use ?
One way of getting text from/to the clipboard is using XSel. It's not pretty and requires you to communicate with an external program. But it works and is quite fast.
Not sure if it's the best solution but I know it works :)
[edit]You're right, it seems that xsel does not support images.
In that case, how about a slightly modified GTK version.
def copy_image(f):
assert os.path.exists(f), "file does not exist"
image = gtk.gdk.pixbuf_new_from_file(f)
clipboard = gtk.clipboard_get()
clipboard.set_image(image)
clipboard.store()
Do note that you might have to change the owner if your program exits right away because of how X keeps track of the clipboard.
You might want to use the set_with_data method instead, but that's slightly more work (the image data is only sent when an application requests it, so it needs callback-functions). This has also advantages when you paste in the same application instead of to another application.
I have a small project that uses libglade and use the following to load the xml file:
self.gladefile = "sdm.glade"
self.wTree = gtk.glade.XML(self.gladefile)
self.window = self.wTree.get_widget("MainWindow")
if (self.window):
self.window.connect("destroy", gtk.main_quit)
dic = { "on_button1_clicked" : self.button1_clicked,
"on_MainWindow_destroy" : gtk.main_quit}
self.wTree.signal_autoconnect(dic)
After converting my project in glade, what structural changes do I need to make?
I'm on Ubuntu 9.04.
You need to use gtk.Builder instead. This class can load any number of UI files, so you need to add them manually, either as files or as strings:
self.uifile = "sdm.ui"
self.wTree = gtk.Builder()
self.wTree.add_from_file(self.uifile)
Instead of get_widget, just use get_object on the builder class:
self.window = self.wTree.get_object("MainWindow")
if self.window:
self.window.connect("destroy", gtk.main_quit)
To connect the signals, just use connect_signals, which also takes a dictionary:
dic = { "on_button1_clicked" : self.button1_clicked,
"on_MainWindow_destroy" : gtk.main_quit}
self.wTree.connect_signals(dic)
It used to be the case (at least in GTK+ 2.12, not sure if it's still the same) that you could call connect_signals only once, any signals which are not connected during the first invocation will never be connected. This was different in glade, so be careful if you relied on that feature before.
Torsten's answer is correct, but a little incomplete, so in the spirit of http://xkcd.com/979/ here is the procedure I recently settled on after much trial-and-error:
Open yada.glade in Glade interface designer. Go to edit->project and change the project type to GtkBuilder and make sure it targets the latest version (2.24 as of this writing). Save the file, being sure that it saves in GtkBuilder format, and change the name from yada.glade to yada.ui
Open yada.py and change the following code:
gladefile = relativize_filename(os.path.join("glade", "yada.glade"))
self.wTree = gtk.glade.XML(gladefile, self.windowname)
to:
uifile = relativize_filename(os.path.join("glade", "yada.ui"))
self.wTree = gtk.Builder()
self.wTree.add_from_file(uifile)
Similarly change all instances of self.wTree.get_widget(...) to self.wTree.get_object(...)
Change self.wTree.signal_autoconnect(dic) to self.wTree.connect_signals(dic)
If your code depends on the name assigned the widget in the interface designer, change widget.get_name() to gtk.Buildable.get_name(widget). widget.get_name() now just returns the widget type. EDIT: You also need to change widget.set_name('my_widget') to gtk.Buildable.set_name(widget, 'my_widget').
Delete import gtk.glade
I found numerous unused signals defined in the yada.ui xml file, I had to open the xml file and manually delete them to eliminate the warnings they caused.