Trouble with widget size and adding new widgets - python

I ran into an issue tonight that involves resizing a QTextBox in a QGridLayout. The code is mostly self-explanatory. I set the QTextBox to span 10 cells down in my init_ui. I have a window size of 500x500.
def init_ui(self):
self.message_body = QTextEdit()
self.layout.addWidget(self.message_body, 2, 0, 9, 7)
self.show()
And then in a later method, changeSize, I am successfully able to change the size of QTextEdit. From this method I call the next method to load titles that will appear below the 445x280 QTextEdit. Loading these titles calls for new widgets to be added to the layout. Which is apparently a problem. I don't know if this is poor styling or not. Should all of the widgets be added in init? Either way when
self.layout.addWidget(lbl_title, 10, i)
runs. I lose my resized QTextEdit. Even if I follow it with another resize function.
Here are the two methods implicated
def changeSize(self):
self.message_body.resize(445,280)
self.loadTitles()
def loadTitles(self):
titles = Movie.title_library
for i, my_title in enumerate(titles):
lbl_title = QLabel(my_title)
## This is the line that refreshes the size to span 10x8 units
self.layout.addWidget(lbl_title, 10, i)
self.message_body.resize(445,280)

I figured out the solution. I needed to remove the message body widget before reinstating it. The code looked like
self.layout.removeWidget(self.message_body)
self.layout.addWidget(self.message_body,2,0,4,7)

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)

Auto resize QLabel to fit updated QTableWidget span

I have a QTableWidget, and I have a QLabel that I put inside a cell of the table using .setCellWidget().
During run-time I change the span of the QTableWidget cell where the QLabel is, using .setSpan()
BUT when I change the span of the cell where the QLabel is, the QLabel does not resize.
Some code and screenshot below:
def generate_table(self):
global gtable
table = QTableWidget(20, 60)
gtable = table
def create_task(self):
task_widget = QWidget()
task_layout = QHBoxLayout()
task_widget.setLayout(task_layout)
task = QLabelClickable(the_task_name)
task_layout.addWidget(task)
gtable.setCellWidget(selected_row_column[0], selected_row_column[1], task_widget)
// if I include this part of the code, everything looks fine, both cell, widget and label scale properly, as visible through background color, below line is not the problem, notice its in the same function as where I set the cell widget
the_duration = 3
gtable.setSpan(selected_row, selected_column, 1, the_duration)
// Below is how I change the cell span. The rrow and ccolumn are integers, basically just cell coordinates
def save_task(self):
gtable.setSpan(rrow, ccolumn, 1, w_dr.value())
(there's a ton of code all over the place so I included what I thought is relevant, let me know what other parts of the code I should include)
This is what it should look like: (this is what the first span-changing line does)
This is what it looks like: (this is what the last line does)
My question is, How do I resize the QLabel / QWidget to auto fit the cell's updated size?
You can see the first span as correct because it's applied in the same event loop that would update the geometries of the view.
Spanning does not automatically do that (which could be a bug), so the solution is to use updateGeometries(), which:
Updates the geometry of the child widgets of the view.
Which means that all widgets of the view will be correctly resized and updated, including scroll bars and cell widgets.
def save_task(self):
gtable.setSpan(rrow, ccolumn, 1, w_dr.value())
gtable.updateGeometries()
A very important suggestion: avoid using globals, they are not handy as one would think, and in fact the often cause problems and bugs that are difficult to track; use instance members instead (eg. self.gtable).

ipywidget interactive hiding visibility

I would like to make an interactive module with ipywidgets.
So far so good but I'm stuck.
I want to hide the visibility of a certain ipywidget object dependent on a certain situation, and I want my printed text to show up above the widget and stay there.
dropdown=widgets.Dropdown(
options={'Coffee machine': 1, 'Washing machine': 2, 'Water Heater': 3, 'Heating System': 4, 'Dryer': 5, 'Oven': 6, 'Microwave': 7, 'Other':8},
value=1,
description='Apparaat:',
)
text_new=widgets.Text()
def text_field(value):
if(value==8):
display(text_new)
text_new.on_submit(handle_submit)
else:
text_new.visible(False) #Doesn't work but I want something like this
print("Today you had an increase in electricity consumption, would you like to name this device?") #This just be above the dropdown menu and be stuck
i=widgets.interactive(text_field, value=dropdown)
display(i)
What this does now:
When "Other" is checked in the dropdown menu, a text box appears where the user can type something.
However, when checking another machine, the text box stays there.
I just need a "hide" function but I can't seem to find one that works.
Also, after checking another option on the dropdown, the print dissapears, not coming back.
Had same problem so i found in
boton.layout.visibility = 'hidden'
or
check.layout.display = 'none'
they made some changes... i got if from here
Cannot create a widget whose initial state is visible=False
Given a widget:
import ipywidgets
button = ipywidgets.Button()
There are two direct ways to hide the the widget, with a notable difference.
Hide and unhide the widget without affecting overall page layout:
# Turn the widget "invisible" without affecting layout
button.layout.visibility = "hidden"
# Make the widget visible again, layout unaffected
button.layout.visibility = "visible"
Hide and unhide the widget and collapse the space that the widget took up:
# Hide widget and collapse empty space
button.layout.display = "none"
# Re-add the widget, adjusting page layout as necessary.
button.layout.display = "block"
When to use each one? As a rule of thumb, use layout.visibility so the page layout is not constantly jumping around as visibility is toggled. However, for very large widgets, consider using layout.display to avoid huge blank spaces.
For more general CSS information that applies here, see What is the difference between visibility:hidden and display:none?
In addition to the accepted answer, if you want to dynamically change the visibility of a control, you can declare the layout variable and reuse.
layout_hidden = widgets.Layout(visibility = 'hidden')
layout_visible = widgets.Layout(visibility = 'visible')
Like attach to an event:
def visible_txt(b):
text_box.layout = layout_visible
def hidden_txt(b):
text_box.layout = layout_hidden
btn_visible.on_click(visible_txt)
btn_hidden.on_click(hidden_txt)

pygtk.HBox not redrawing after add

I have a program written in Python, using PyGTK+Glade. I use Glade to create the Layout, and internally, I create some other elements, including a list of labels. I have a VBox of size 3, each of these 3 elements containing an EventBox which contains an HBox.
Each HBox will contain a dinamically changing set of Labels. The problem is that after Adding elemens to the HBox, it doesn't show anything or doesn't get redraw.
As I said, there are some events/functions that change the HBoxes, however, something like this even doesn't work:
def __init__(self):
self.builder = gtk.Builder()
self.builder.add_from_file("maininterface.glade")
self.window = self.builder.get_object("mainWindow")
self.fila1 = self.builder.get_object("hbox1")
self.fila2 = self.builder.get_object("hbox2")
self.fila3 = self.builder.get_object("hbox3")
self.window.show_all()
lab0 = gtk.Label("XXXXXX")
self.fila1.add(lab0) #this label is not shown
#if I uncomment the next line, it works:
#self.window.show_all()
Obviously, I am missing something, I don't know what. I could make all the adds before show_all() but that just works for initialization, the program will remove/add elements on the fly.
PD: I used pack_end() instead of add() but the result is the same.
You will need to call gtk.Widget.show() on each label that you add to the HBox. Alternatively, you can call gtk.Widget.show_all() on the HBox after adding one or more labels.

QScrollView with no scrollbars

I'm trying to make a QScrollView with around 100 different labels and buttons.
But after I add them, the scrollbars do not appear.
here is an example of the code I wrote:
self.btn = {}
self.scroll = QScrollView(self)
self.scroll.setGeometry(QRect(0,0,300,300))
self.scroll.enableClipper(True)
vp = self.scroll.viewport()
for i in range(0,100):
self.btn[i] = QPushButton(vp)
for i in range(0,100):
self.scroll.addChild(self.btn[i],1,50*i)
self.scroll.setVScrollBarMode(QScrollView.AlwaysOn)
make the scrollbar appear but not to work.
The buttons get added to the QScrollView but I can't scroll down to see them all
what am I doing wrong? I'm using qt3.
You don't add all your little items to the scrollview. You have to insert a single, large container (a QFrame derived class, for example) into the scrollview that contains all your smaller widgets.
Actually you just need to give the scroll-view a layout and add your widgets to this. Adding them as sub-widgets of one big widget within the scrollview will do this for you, but it's messier.

Categories

Resources