Combining Glade XML with HeaderBar - gtk3

I am a beginner to using Glade and PyGTK and I am trying to create a window with a custom title bar that is created using the header bar component and the rest of the UI being done through a GLADE file. However instead of getting one window I am getting two different windows, one containing the header bar and the other containing the UI components developed in Glade. Could someone point me as to how to make them appear in the same window. PFB the code that has been written so far :
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio
class HeaderBarWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="MLPP")
self.set_border_width(10)
self.set_default_size(400, 200)
hb = Gtk.HeaderBar()
hb.set_show_close_button(True)
hb.props.title = "MLPP"
self.set_titlebar(hb)
titleBarImage = Gtk.Image()
titleBarImage.set_from_file('TitleIcon.png')
hb.pack_start(titleBarImage);
gladefile = "MLPP.glade"
builder = Gtk.Builder()
builder.add_from_file(gladefile)
self.add(builder.get_object("window1"))
win = HeaderBarWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

builder.add_from_file(gladefile)
self.add(builder.get_object("window1"))
Here you seem to get a "window" and add that to your intial Window. I guess you don't want to add the window defined in the Glade file, but one of its children. You probably have a Box or some other container defined. Try to get_object(box1) or however you identify your widget of desire.

Related

TreeView multiple selection does not work correctly after changing selection without UI

This is potentially a bug, though perhaps I'm misunderstanding something.
Brief description
Basically, I have found that using "Shift+Arrows" to do multiple selection in a Gtk.TreeView does not work correctly after changing the selection using Gtk.TreeSelection.select_iter. On the other hand, if you change the selection by clicking on a row and then pressing "Shift+Arrows", the selection behaves as one would expect.
I should note that if you change the selected row by calling Gtk.TreeSelection.select_iter, the UI updates as you would expect and calling Gtk.TreeSelection.get_selected_rows() returns the rows it should. It's only when you then try to select multiple rows using the arrow keys that you get strange behavior.
This is perhaps best illustrated in this self contained example, which I've tried to make as simple as possible:
Code
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class TreeViewBug(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect('destroy', Gtk.main_quit)
# Create model consisting of row path and a name
self.treeModel = Gtk.ListStore(int, str)
self.treeModel.append([0, 'alice'])
self.treeModel.append([1, 'bob'])
self.treeModel.append([2, 'chad'])
self.treeModel.append([3, 'dan'])
self.treeModel.append([4, 'emma'])
self.treeView = Gtk.TreeView()
self.treeView.append_column(Gtk.TreeViewColumn('path', Gtk.CellRendererText(), text=0))
self.treeView.append_column(Gtk.TreeViewColumn('name', Gtk.CellRendererText(), text=1))
self.treeView.set_model(self.treeModel)
# Allow for multiple selection
self.treeView.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
self.add(self.treeView)
def run(self):
self.show_all()
# Focus the TreeView so we can test multiple select via keyboard without clicking on a row
self.treeView.grab_focus()
# Manually change the selected row to the row with "chad"
chadIter = self.treeModel[2].iter
self.treeView.get_selection().select_iter(chadIter)
print('Press "Shift+Down" and see what happens')
print(' it should select "chad, dan", but instead it selects "bob, chad"')
print('Afterwards, try clicking on "chad" and then pressing Shift+Down. It should behave normally')
Gtk.main()
if __name__ == '__main__':
tv = TreeViewBug()
tv.run()
Things I've tried
I initially encountered the bug when my code changed the selected row via Gtk.TreeSelection.select_iter in response to a button click.
I've also tried:
adding a custom select function (Gtk.TreeSelection.set_select_function)
clearing the selection before changing it (Gtk.TreeSelection.unselect_all)
changing the selection asynchronously (GLib.idle_add).
redrawing TreeView after changing selection
Speculations
I'm guessing that TreeView/TreeViewSelection has some internal state variable tracking selection and row that, for some reason, isn't getting properly updated when TreeSelection.select_iter is called. These variables are probably related to UI features, because TreeSelection.get_selected_rows still works properly. Also it makes sense the UI would need additional state information since the UI logic of multiple selection depends on previous UI interaction (Shift+Down behaves differently when extending a selection depending on whether you initially selected upwards or downwards)
Because a Gtk.TreeView uses MVC, you actually need to set the cursor of the treeview. This may affect the rest of the program, depending on what you are doing. Example:
#chadIter = self.treeModel[2].iter
#self.treeView.get_selection().select_iter(chadIter)
path = 2
column = self.treeView.get_column(0)
edit = False
self.treeView.set_cursor(path, column, edit)

Python: Changing the select colour in a GtkTreeview

I want to disable the selection colour at a treeview. So I want to set the selected color to white with modify_base. I found this solution, but it doesn't work. This is my code:
import gi
from gi.repository import Gdk, Gtk
gi.require_version('Gtk', '3.0')
treestore = InterfaceTreeStore()
treeview = Gtk.TreeView()
treeview.set_model(treestore)
treeview.modify_base(Gtk.StateFlags.SELECTED, Gdk.Color(red=65535, blue=65535, green=65535))
gtk_widget_modify_base has been deprecated since 3.0. You could have used gtk_widget_override_background_color, if it wasn't deprecated since 3.16. It's documentation states that:
If you wish to change the way a widget renders its background you should use a custom CSS style
However, if you want to disable selection color, the simpliest way is to unselect.
Your "changed" signal callback might look something like this:
def changed_cb(selection):
model, iter = get_selected (selection)
# if there is no selection, iter is None
if iter is None:
return
# do something useful
# now unselect
path = model.get_path(iter)
selection.unselect_path(path)
path.free() # not sure if python frees it automatically

Scala Swing: Changing BorderPanel central component new Component not visible

I'm changing the centre area on a Scala Swing Border Panel. The old component disappears, but the new component does not appear, until I resize the window manually with the mouse. I've tried using different components and repainting, but nothing makes the new component appear except manually resizing the window with the mouse.
def splitDisp(mapCanv: VistaIn): Unit =
{
val canv2 = newMapCanv
panel.layout(canv2) = BorderPanel.Position.Center
canv2.repaint
thisScn.repaint //ref to the Frame instance
panel.repaint
thisScn.repaint
canv2.repaint
}
I'm using 2.10.0M5 in Windows 7.
Try calling revalidate() and then repaint().

Mac style joined buttons (segmented control) with Gtk

I've seen it done in the ubuntu software center, and with a few gnome apps.
Where two buttons look like a single rectangle with a line through it, how is this being done?
In GTK 3.0 and later, use the INLINE_TOOLBAR style class or LINKED style class.
#!/usr/bin/env python
from gi.repository import Gtk
button_names = [
Gtk.STOCK_ABOUT,
Gtk.STOCK_ADD,
Gtk.STOCK_REMOVE,
Gtk.STOCK_QUIT]
buttons = [Gtk.ToolButton.new_from_stock(name) for name in button_names]
toolbar = Gtk.Toolbar()
for button in buttons:
toolbar.insert(button, -1)
style_context = toolbar.get_style_context()
style_context.add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR)
window = Gtk.Window()
window.set_size_request(200, 50)
window.add(toolbar)
window.connect('delete-event', Gtk.main_quit)
window.show_all()
Gtk.main()
Fwiw, since I recently had the same question, here's another answer with an up-to-date citation and using C instead of some wrapper. (I use GTKmm, but I feel we should refer to the native C API unless a wrapper is explicitly stated.)
I wanted to achieve the same thing and eventually stumbled upon the answer, at the official page HowDoI: Buttons. This effect is achieved by putting the targeted Buttons in a Container and giving the latter the CSS class linked. (That page says using a Box is normal, but asBox will probably be deprecated soon and Grid is superior anyway... use a Grid.)
So:
GtkWidget *const grid = gtk_grid_new ();
GtkStyleContext *const context = gtk_widget_get_style_context (grid);
gtk_style_context_add_class (context, "linked");
/* Add your Buttons to the Grid */
That link also discusses some other handy embellishments we can make to GtkButtons, including the classes suggested-action and destructive-action.
For similar questions, it's very illustrative to browse the source of (A) an application that does what you want to replicate and (B) the Adwaita theme CSS.

gtkmm button not maintaining size and location

I have created two gtkmm button and added to HBox object. I called pack_end, and maintained the size as 21,20. But, the sizes are not maintained. Here is the code i have written and the window that i got while running the program.
Note: MYWindow is subclass of Gtk::Window
void MYWindow::customizeTitleBar()
{
//create a vertical box
Gtk::VBox *vBox = new Gtk::VBox(FALSE,0);
//create a horizontal box
Gtk::HBox *hBox = new Gtk::HBox(TRUE,0);
hBox->set_border_width(5);
//create title bar image
Gtk::Image *titleBarImage = new Gtk::Image("src/WindowTitleBar.png");
titleBarImage->set_alignment(Gtk::ALIGN_LEFT);
// hBox->pack_start(*titleBarImage,Gtk::PACK_EXPAND_WIDGET,0);
//create cloze button for window
mButtonClose = new Gtk::Button;
(*mButtonClose).set_size_request(21,20);
Gtk::Image *mImage = new Gtk::Image("src/Maximize.jpeg");
(*mButtonClose).add(*mImage);
(*mButtonClose).set_image_position(Gtk::POS_TOP);
// connecting close window function when cliked on close button
//(*mButtonClose).signal_clicked().connect( sigc::mem_fun(this, &MYWindow::closeWindow));
hBox->pack_end(*mButtonClose,Gtk::PACK_EXPAND_WIDGET,0);
Gtk::Button * mBtton = new Gtk::Button;
mBtton->set_size_request(21,20);
Gtk::Image *img = new Gtk::Image("src/Maximize.jpeg");
mBtton->add(*img);
mBtton->set_image_position(Gtk::POS_TOP);
hBox->pack_end(*mBtton,Gtk::PACK_EXPAND_WIDGET,0);
vBox->add(*hBox);
//drawing area box
Gtk::HBox *hBoxDrawingArea = new Gtk::HBox;
Gtk::DrawingArea *mDrawingArea = new Gtk::DrawingArea;
hBoxDrawingArea->pack_start(*mDrawingArea,Gtk::PACK_EXPAND_WIDGET,0);
vBox->add(*hBoxDrawingArea);
//status bar hBox
Gtk::HBox *hBoxStatusBar = new Gtk::HBox;
vBox->add(*hBoxStatusBar);
this->add(*vBox);
this->show_all();
}
I am not yet a gtk expert (but I'm learning), here's one thing you can try, which is what I've been doing.
Make a little standalone project using glade. Glade makes it really easy to screw around with all the packing settings so you can immediately see the effects of your changes.
I think in the case of resizing the window, you'll have to save the glade file and run your program (using gtkbuilder to render the glade file) and manually resize the window to see the effect, but once you make the standalone project, you can use it for other gtk testing.
And if you're like me, you'll get swayed by the wonderfulness that is glade and build your whole system that way.
But basically, it sounds like a packing issue, because I've got buttons that don't resize all over the place.
As for not moving, I'm not sure you can do that, but again I'm not an expert. I think you should be able to pin the size of some if not all of the hbox pieces so that the button inside them will not move, but I'm not sure what happens if you don't have any hbox parts that can't be variably sized to take up the slack when you grow the window.
Again, sounds like something fun to try in glade. :-)
I think you pack to FALSE , Maybe this is the problem :
Gtk::HBox *hBox = new Gtk::HBox(TRUE,0)
I use python gtk with something like this:
box1.pack_start(box2,False)