How to stop expansion of QGridLayout element - c++

I have couple of labels (dynamically generated on button click and can vary in numbers which read from configuration file) and added to QGridLayout. Upon load which looks like below ...
these labels are generated and added as below
QGridLayout * layout = new QGridLayout(ui->pageInputWindow);
layout->setSpacing(5);
layout->setMargin(0);
ui->pageInputWindow->setLayout(layout);
// for question purpose I take number of row and col to 3
// but in actual they will be read from configuration file
for(int row = 0; row < 3; row ++)
{
for(int col = 0; col < 3; col++)
{
QLabel * placeHolder = new QLabel(ui->pageInputWindow);
placeHolder->setText("LABEL "+QString::number(10*(row+1) + col + 1));
layout->addWidget(placeHolder, row, col);
}
}
These label are placed here for rendering video streaming by setting pixmap of captured video frames when selected. I am setting pix as ....
// I am getting img object from other class, below code is just a snap of it.
// You can assume img as valid QImage objcet
QImage img
selectedLabel->setPixmap(QPixmap::fromImage(img).scaled(selectedLabel->size(),Qt::KeepAspectRatio, Qt::FastTransformation));
My ideal scenario is when I select any label it will remain with size which it got when loaded according to configuration settings at runtime. But when I start streaming below event happened.
Suddenly selected label ( see black pictured label at 'LABEL 11' position) starts expansding to much even causing application to expand. Idealy I want above event as below ( assume white background is video frame ) without any expansion.
My question is how can I stop this undesirable expansion of labels while setting pix map on them ?

Set the labels' size policies to ignored:
placeHolder->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);

Related

Placing the Same QImage Multiple Times in a Loop

I am trying to build some sort of media player. Currently, the basic functions of the media player work and there is a video progress bar that show where in the video they are and how long. This progress bar is a slider and what I want to do is place tick marks on this progress bar (like bookmarks but for videos) based on user input. I have this working as a QList. However, when I save the user input into a text file containing the tick mark locations and the video location. It loads everything contained in the file properly besides the tick markers which are just QImages. It only loads the last tick marker
Currently, the code is a for loop that takes the positions listed calculates the position the tick marker must go on the progress bar and places it there.
Shown below is the portion of code that is related to this issue:
int slider_xpos = ui->VideoProgressSlider->x();
int slider_ypos = ui->VideoProgressSlider->y();
int slider_width = ui->VideoProgressSlider->width();
while(!Bookmark_Placement.empty())
{
//New Bookmark is initialized
Bookmarker_Label = new QLabel(this);
Bookmark = new QImage();
Bookmark->load("UI_Elements/Bookmark.png");
//Bookmark's image is scaled down
int scaled_width = Bookmark->width()/64;
int scaled_height = Bookmark->height()/64;
QImage *Bookmark_Scaled = new QImage(Bookmark->scaled(scaled_width,Bookmark->height(),Qt::KeepAspectRatio));
Bookmarker_Label->setPixmap(QPixmap::fromImage(*Bookmark_Scaled));
//Takes the Bookmark's position off of QList
int Bookmark_Position = Bookmark_Placement.last();
Bookmark_Placement.removeLast();
//Places Bookmark in the proper position
double offset = ((double)Bookmark_Position/(double)Bookmark_Count)*(double)slider_width;
int Bookmarker_Label_xpos= slider_xpos + (int)offset;
Bookmarker_Label->setGeometry(Bookmarker_Label_xpos,slider_ypos - scaled_height,scaled_width,scaled_height);
Bookmarker_Label->show();
}

Wrapping text in GTK3 treeview

I have trouble getting TreeView in GTK3 to wrap text correctly.
I set it up to wrap in this way:
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_mode().set_value(Pango::WRAP_WORD_CHAR);
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_width().set_value(200);
This works, text is wrapped, but when I resize the window and make it bigger, there is a lot of ugly white-space above and below cell with long text. It seems, that GTK reserves height for cell based on wrap width. Which makes no sense to me.
I tried to get around with setting needed in signal_check_resize with calculating needed width like this:
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
auto width = this->get_allocated_width()
- mTreeView.get_column(0)->get_width()
- mTreeView.get_column(1)->get_width();
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_width().set_value(width-100);
this->forceRecreateModel = true; //Needed to work
But this lets me only make window bigger. It cannot be shrinked, after it was resized.
The question is, how this is properly done?
I am using gtk3.20.3-1 and gtkmm3.20.1-1 on Arch linux.
EDIT: fixed typo in the title...
In the end I found how to do it.
In the setup of the window (for me constructor of the window derived class) it was necessary to set column to be AUTOSIZE in order to allow shrinking of the width.
//Last Column setup
{
mTreeView.append_column("Translation", mColumns.mEnglish);
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
pColumn->set_sizing(Gtk::TreeViewColumnSizing::TREE_VIEW_COLUMN_AUTOSIZE);
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_mode().set_value(Pango::WRAP_WORD_CHAR);
}
Also there is needed to set correct wrap width on every resize. Without this, height of the row was as big as it would be necessary for currently set wrap_width with no regard on current width (resulting in big padding on the top, when stretched more and prohibiting to make window smaller).
This code was also in the constructor.
this->signal_check_resize().connect([this]()
{
//calculate remaining size
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
auto width = this->get_allocated_width()
- mTreeView.get_column(0)->get_width()
- mTreeView.get_column(1)->get_width()-30;
//minimum reasonable size for column
if(width < 150)
width = 150;
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_width().set_value(width);
//debounce
static auto oldsize = 0;
{
oldsize = width;
//trigger redraw of mTreeView (by clearing and refilling Model,
//it is done in 100ms pulse)
this->mRedrawNeeded = true;
}
});
And maybe it is worth noting, that I have mTreeView encapsulated in Gtk::ScrolledWindow. So this is a chunk which comes before column setup. :)
//in class is: Gtk::ScrolledWindow mScrollForResults;
//scrolling area
mGrid.attach(mScrollForResults, 0,2,10,1);
mScrollForResults.set_hexpand();
mScrollForResults.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC,
Gtk::PolicyType::POLICY_ALWAYS);
mScrollForResults.set_margin_top(10);
mScrollForResults.set_min_content_width(400);
mScrollForResults.set_min_content_height(200);
mScrollForResults.add(mTreeView);
//results treeView
mRefListStore = Gtk::ListStore::create(mColumns);
mTreeView.set_model(mRefListStore);
mTreeView.set_hexpand();
mTreeView.set_vexpand();

How to change the background color from the header(horizontal / vertical) QTableWidget on Qt?

I would like to know how to change the background color from the headers (horizontal / vertical) from the object QTableWidget on Qt.
I already Know how to change all the headers together, using :
ui->tableWidget->setStyleSheet("QHeaderView::section {background-color:red}");
But I need change individually the items. Obviously if this is possible .
There are at least 2 ways to solve this problem. Very easy one:
Just use setHeaderData() and set specific colors for specific sections.
QTableView *tview = new QTableView;
QStandardItemModel *md = new QStandardItemModel(4, 4);
for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 4; ++column) {
QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
md->setItem(row, column, item);
}
}
tview->setModel(md);
tview->model()->setHeaderData(0,Qt::Horizontal,QBrush(QColor("red")),Qt::BackgroundRole);
tview->show();
But u nfortunately it will not work on some systems... Qt uses the platform style. For example, my Windows doesn't allow to change header's color. So this code doesn't work on my machine. Fortunately, it can be solved easily with changing global style. So next code works:
//... same code ...
tview->show();
QApplication::setStyle(QStyleFactory::create("Fusion"));
If you don't want to change style, then you should create your own HeaderView. Probably, something similar as here.

Qt programming QComboBox

I am using Qt and C++ to add some features to a freeware called: EASYPAINT.
I had to add a more intuitive method in which the users can see the actual width directly from the tool instead of changing numbers. ( just like in the new windows paint , where you can actually see the line thickness and not pixels.)
I am using a QComboBox. My question is (look at the code first), instead of having 20 (penSizeList->addItem), I know we can have addItems.... But what about the icon. for each Item, will I have to search for 20 different line thickness.png and add them? Or is there another method I can use?
And also, how can I get rid of the string in addItem, and only keep an image or icon in the QComboBox.
QComboBox *penSizeList = new QComboBox();
penSizeList->setIconSize(QSize(100,100));
penSizeList->setStatusTip("Pen Size");
QIcon ONEpxIcon(":/media/actions-icons/clear-gray.png");
QIcon THREEpxIcon(":/media/instruments-icons/canvas-lines1.png");
penSizeList->addItem(ONEpxIcon,"1px");
penSizeList->addItem(THREEpxIcon,"2px");
penSizeList->addItem(THREEpxIcon,"3px");
penSizeList->addItem(THREEpxIcon,"4px");
penSizeList->addItem(THREEpxIcon,"5px");
penSizeList->addItem(THREEpxIcon,"6px");
penSizeList->addItem(THREEpxIcon,"7px");
penSizeList->addItem(THREEpxIcon,"8px");
penSizeList->addItem(THREEpxIcon,"9px");
penSizeList->addItem(THREEpxIcon,"10px");
penSizeList->addItem(THREEpxIcon,"11px");
penSizeList->addItem(THREEpxIcon,"12px");
penSizeList->addItem(THREEpxIcon,"13px");
penSizeList->addItem(THREEpxIcon,"14px");
penSizeList->addItem(THREEpxIcon,"15px");
penSizeList->addItem(THREEpxIcon,"16px");
penSizeList->addItem(THREEpxIcon,"17px");
penSizeList->addItem(THREEpxIcon,"18px");
penSizeList->addItem(THREEpxIcon,"19px");
penSizeList->addItem(THREEpxIcon,"20px");
connect(penSizeList,SIGNAL(activated(int)), this, SLOT(penValueChanged(int)));
Try to do this in loop.
penSizeList->addItem(ONEpxIcon,"1px");
for(int i = 2; i < 21 ; i++)
{
penSizeList->addItem(THREEpxIcon,QString("%1px").arg(i));
}
Or if you have different icons for each line:
for(int i = 1; i < 21 ; i++)
{
penSizeList->addItem(QIcon(QString("iconLine%1.png").arg(i)),QString("%1px").arg(i));
}
If you want only icons, set empty string:
penSizeList->addItem(icon,"");
If you want full image then you should set this image as background. For example:
QPixmap pxmap("G:/2/qt.jpg");
QStandardItemModel *md = new QStandardItemModel;
QStandardItem *iii = new QStandardItem;
iii->setBackground(QBrush(Qt::red));
iii->setText("ss");
QStandardItem *iiii = new QStandardItem;
iiii->setBackground(QBrush(pxmap));
iiii->setText("ss");
md->setItem(1,0,iii);
md->setItem(0,0,iiii);
ui->comboBox->setModel(md);

Spacing between widgets in QHBoxLayout

I'm trying to create a GUI with QtCreator. For this GUI, I need to display several images with different sizes next to each other. These images should be touching each other.
I use a QWidget with a QHBoxLayout, where I add the labels (with different sizes) containing the images.
According to related questions, I should use setSpacing and setContentsMargin to remove these spaces, but that won't work; I tried several times.
Here's the code:
QWidget *widget = new QWidget(ui->tagcloud);
QHBoxLayout * l = new QHBoxLayout(widget);
ui->tagcloud->setWidget(widget);
for(int i=0;i<list.size();++i)
{
QLabel *lab = new QLabel;
QPixmap pic((list[i].imgPath).c_str()); //This fetches the image
int sizeChange = 50 + (2*list[i].percent); //Calculates the size of the image
lab->setFixedSize(QSize(sizeChange, sizeChange));
lab->setPixmap(pic);
lab->setScaledContents(true);
l->addWidget(lab);
l->setSpacing(0);
}
However, when I run this, the spacing remains the same (i.e. definitely not zero).
If I add more labels to the layout, the spacing seems to get smaller.
Can anyone explain or help me? Thanks!
Setting spacing to 0 and adding stretch before and after works for me :
l->addStretch();
for(int i = 0; i < list.size(); ++i)
{
QLabel *lab = new QLabel;
QPixmap pic((list[i].imgPath).c_str()); //This fetches the image
int sizeChange = 50 + (2*list[i].percent); //Calculates the size of the image
lab->setFixedSize(QSize(sizeChange, sizeChange));
lab->setPixmap(pic);
lab->setScaledContents(true);
l->addWidget(lab);
}
l->addStretch();
l->setSpacing(0);
Also this works I think
l->setSizeConstraint(QLayout::SetMaximumSize);