Controling button/hbox sizes in gtk - python

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.

Related

PyQT5 - Is it impossible to nest widgets within new widgets?

I have frames designed in seperate scripts that are all called to this central gui script which shows them using QMainWindow as one would expect.
However, I am trying to redesign the Main Window in such a way that there is a permanently fixed frame on the right hand side, and a tabbed frame on the left.
Before I attempted to make this happen, I could display, using setlayout, all of the frames on the mainwindow at once, however, when I try to add several of these"sub-widget" frames to my new tabbed frame everything gets annoying...
... effectively, I am taking already functioning widgets (designed w/ QFrame) called from other scripts and trying to make 2 new widgets with them (QTabWidget, for the left frame, and QGroupBox for the right). However, when run, the window pops up with my groupbox and tabwidgets completely empty, and my "sub-widgets" are displayed in new windows.
Here is a snippet:
tab_frame = QWidget()
tab_frame.layout = QVBoxLayout() #-------------------- Layout
tab_frame.layout.addWidget(self.FRAME_FROM_OTHER_SCRIPT)
tab_frame.layout.addStretch(1)
#### Tabs Parent ####
tabs = QTabWidget()
tabs.layout = QVBoxLayout()
tabs.addTab(tab_frame,"Tab 1")
#### Fixed Frame ####
vbox_az = QGroupBox()
vbox_az.layout = Qt.QVBoxLayout() #------------------------ Layout
vbox_az.layout.addWidget(self.FRAME_FROM_OTHER_SCRIPT)
self.main_grid = QGridLayout() #--------------------------- Layout
self.main_grid.addWidget(tabs,0,0,1,2)
self.main_grid.addWidget(vbox_az,0,2,1,3)
self.main_grid.setColumnStretch(2,1)
self.main_grid.setColumnStretch(5,1)
self.main_window.setLayout(self.main_grid)
I am unsure of what is actually happening... are widgets unable to be nested within other widgets?
Because setLayout relies on a layout input and not a widget I am unsure of how else to attack this problem other than by grouping my "sub-widgets" into groupboxes but I do not know why it's going so wrong.
Here is a picture screen-grab to illustrate further:
(for the sake of my question I have asked to split my window into two portions though I am actually splitting it three times)

pyqt: how to use scroll area that contains an outsized label [duplicate]

I want to overlay two widgets in QtDesigner:
There is the big QTextBrowser, and below in the down right corner should be a non-interactiv label that I am going to use as a drag-grip to resize the window (the main widget is frameless so I need to implement it).
Usually this label will sit below the QTextBrowser, which leaves on the left of the grip-label a lot of unused space. So I want to put the grip-label above the QTextBrowser. I want to achieve this in QtDesigner. But the code would look like:
QHBoxLayout *layout = new QHBoxLayout(videoWidget);
QLabel *overlayWidget = new QLabel();
overlay->setAlignment(Qt::AlignCenter);
overlay->setText("Overlaid Text");
layout->addWidget(overlay);
Or as I already did in python:
self.textedit = QTextBrowser(self);
...
gripImage=QLabel(self.textedit);
There the part between the brackets is the parent widget.
That's how it looks right now, but this is not what I want:
This is usually simplest to achieve by using QGridLayout. It allows widgets to occupy the same grid cells. For this particular problem, a 1x1 grid is enough.
Steps to try it out with designer:
Create new form, plain Widget for simplicity
Add a text edit to it (drag and drop from Widget Box), and from Object Inspector you should see it becomes child of the root widget
Add a label to it (drag and drop from Widget Box), and from Object Inspector you should see it becomes child of the root widget
Right click on the root widget (easiest in the Object Inspector), and from the bottom of context menu, select Lay out > - Lay out in Grid
Right click on the label, and from Layout alignment > set it aligned to the corner you want
Done. Here's what it looks like in my Designer:
Now adapt above to your real form.
Ok, it appears achieving above with Designer is hard, and perhaps a bit a matter of luck of doing things just right... Designer just doesn't support doing what you want, it seems.
For clarity this is a complete source code:
QGridLayout *layout = new QGridLayout(widget);
QTextBrowser *textBrowser = new QTextBrowser();
QLabel *label = new QLabel();
label->setText("Overlaid Text");
//label gets positioned above textBrowser and is an overlay
layout->addWidget(textBrowser, 0, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(label, 0, 0, Qt::AlignRight | Qt::AlignBottom);
I had the same problem but I did not manage to add Overlapping widgets in QtDesigner. Instead, I had to create the overlapping one dynamically after initializing my MainWindow.
I've got two widgets:
dataset_tableWidget (tableWidget)
spinner_dataset_tableWidget (QtWaitingSpinner)
and I wanted to make spinner_dataset_tableWidget spin over the dataset_tableWidget.
After initializing the MainWindow you can do:
#Crating QtWaitingSpinners dinamically and positioning it over the tableWidgets
dataset_tableWidget = QtWaitingSpinner(dataset_tableWidget)
dataset_tableWidget.setSizePolicy(dataset_tableWidget.sizePolicy())

Python Gtk3 controlling button size

The button size should be controlled by packing HBox in VBox but my two buttons still have size depending on text:
first=Gtk.VBox()
second=Gtk.HBox()
third=Gtk.VBox()
fourth=Gtk.HBox()
but1=Gtk.Button(label="any title")
first.pack_start(second,False,False,0)
third.pack_start(fourth,False,False,0)
first.pack_start(but1,False,False,0)
self.data_wp="title of label"
self.label_data=Gtk.Label(label=self.data_wp)
Gtk.Widget.set_size_request(but1,85,15)
but2=Gtk.Button(label=self.data_wp)
Gtk.Container.add(but2,self.label_data)
Gtk.Widget.set_size_request(but2,85,15)
What am I doing wrong? I add button title from label but it shoudn't be the problem, and I tried to set title directly on button - nothing changed. I tried to use only one set of VBox,HBox, but it gave no effect too.
I think the problem here is that you're trying to resize the button using the set_size_request() method of the Gtk.Widget. But set_size_request() only set the minimum size of the widget, so it can still be larger.
I don't know if there is a method to resize the button, but there are the properties width-request and height-request of the Gtk.Widget that you can use.
In your code, it would be:
bt1.set_property("width-request", 85)
bt1.set_property("height-request", 15)

How to hide a layout in PyQt?

My code contains a vertical box layout which is a combination of a vertical box layout in left and one at right. I was wondering if there is a way to hide the left layout with all its widgets when a certain signal is emitted.
You could cheat and use a frame instead of a layout: It works exactly the same way, except for the fact you have to set a layout on the frame for it to work properly. You can then do the following:
from PyQt5 import QtWidgets
# create the frame object.
frame = QtWidgets.QFrame()
# you can do this with any layout - vbox, grid, hbox...
# There will not be more than one item in it anyway.
ly = QtWidgets.QVBoxLayout()
frame.setLayout(ly)
# we're assuming here that parent_layout is some outside layout object.
parent_layout.addWidget(frame)
# hide the frame and its contents
frame.hide()
# show the frame and its contents
frame.show()
I was looking for a solution like this, hope this helps :)
You can't hide a layout, but you can hide a widget.
So first put all the widgets in a container widget. Then connect your signal to the setHidden() slot of the container widget. Your signal should emit True or False, depending on whether you want to hide or show the widgets. Alternatively, you could connect your signal to a simple toggle slot, like this:
def toggleLeftWidget(self):
self.leftWidget.setHidden(not self.leftWidget.isHidden())
In which case, it wouldn't matter what your signal emitted.

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)

Categories

Resources