how to create a qtablewidget with custom header - c++

I'm trying to create an exact copy of the following table in Qt
How would I create a header like that? Is there a way to do it in Qt?

You could customize every single header column by using setHorizontalHeaderItem or just set the text in all column header by using setHorizontalHeadersLabels.
An easy way to implement your attached image is by customizing your own QWidget. Use a vertical layour and consider your Icp (mA) header as a custom label with a center alignment.
Then insert your QTableWidget and set the headers as (3kOmega, 5.1kOmega & 11kOmega). Something like this:
QWidget* container = new QWidget(this);
QVBoxLayout* layout = new QVBoxLayout(this);
// Custom label
QLabel* header = new QLabel(this);
header->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
header->setAlignment(Qt::AlignHCenter);
header->setText("Icp (mA)");
// Custom QTableWidget
QTableWidget* table = new QTableWidget(this);
table->setColumnCount(3);
QStringList LIST;
LIST << "3k" << "11k" << "15k";
table->setHorizontalHeaderLabels(LIST);
table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
table->horizontalHeader()->setStretchLastSection(true);
layout->addWidget(header);
layout->addWidget(table);
container->setLayout(layout);
setCentralWidget(container);
Giving you something like this:

Related

QTabWidget tab displays nothing in one of the tabs

I am trying to create a gui that has a QTabWidget with multiple tabs. As a preliminary test I have created one that has two tabs using the same layouts. The first tab (Page 1) is blank but then the second one shows the QTableView I created. Both tabs were created the exact same way, yet they perform differently. Anyone know why the first one is blank...?
I noticed that if I comment out the line int8Window->setLayout(_layout);. Page 1 shows up with the proper layout and the second tab is blank this time...
Here is the code for the gui:
// Main window and layout
QWidget* mainWindow = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout;
// Tab widget
QTabWidget* tabWidget = new QTabWidget;
// The pages in the tab widget
QWidget* uInt8Window = new QWidget;
uInt8Window->setWindowTitle(QString("Page 1"));
QWidget* int8Window = new QWidget;
int8Window->setWindowTitle(QString("Page 2"));
QTableView* tableView = new QTableView;
QStandardItemModel* model = new QStandardItemModel(5, 5);
for (int row = 0; row < 5; ++row) {
model->setItem(row, 0, new QStandardItem("3"));
model->setItem(row, 1, new QStandardItem(5));
model->setItem(row, 2, new QStandardItem(2));
model->setItem(row, 3, new QStandardItem(1));
model->setItem(row, 4, new QStandardItem(5));
}
tableView->setModel(model);
// Setting the tab page layouts
_layout = new QVBoxLayout;
_layout->addWidget(tableView);
uInt8Window->setLayout(_layout);
int8Window->setLayout(_layout);
// Add the pages to the tab widget
tabWidget->addTab(uInt8Window, "Page 1");
tabWidget->addTab(int8Window, "Page 2");
// Add the tab widget to the main layout and show
mainLayout->addWidget(tabWidget);
mainWindow->setLayout(mainLayout);
mainWindow->show();
Read logs! I'm sure you have a respective warning.
You are assigning same layout to two different widgets. Once layout is assigned to a widget, it is owned by this widget forever.
You need create separate layout for each widget.
I recommend to split this onto couple methods. One is creating a widget for a page (you can use this couple times). Other creating a data model, and other composing tab widget.
Please remember also about memory management! Best approach is to set parent during construction (as parameter of constructor). You have a leak in data model.

How to create custom layout for widget

I'm trying to create a custom widget in QT that looks something like this:
The red squares will be displaying an image/icon.
How can I achieve this layout through coding the widget? I will need to create many of those widgets with the same layout but different values in their labels. Ideally, I will display those widgets as a list with a scrollbar in my mainwindow. But right now I'm struggling to just create the layout for those widgets through code. Any help is much appreciated.
You need to split you design on to separate segments. Each segment can be either a separate sub layout or a widget. In you example, I see the following segments:
Large red icon,
Two labels: TextLabel and 06-November-2014...
Two labels make a vertical box layout,
Vertical box layout and large red icon make a horizontal box layout,
Small red rectangle makes a separate layout,
All layouts make a main layout.
Now lets code this composition:
QLabel *largeRed = new QLabel(this); // Should set an image for this label
QLabel *lbl1 = new QLabel("06-November-2014...", this);
QLabel *lbl2 = new QLabel("TextLabel", this);
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(lbl1);
vLayout->addWidget(lbl2);
vLayout->addStretch();
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(largeRed);
hLayout->addLayout(vLayout);
QLabel *smallRed = new QLabel(this); // Should set an image for this label
QHBoxLayout *hLayout2 = new QHBoxLayout;
hLayout2->addWidget(smallRed, 0, Qt::AlignRight);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(hLayout);
mainLayout->addLayout(hLayout2);
[..]
Use this.
QPixmap big(75,65);
big.fill(Qt::red);
QPixmap small(25,15);
QVBoxLayout *box = new QVBoxLayout;
QWidget *window = new QWidget;
QLabel *bigLab = new QLabel;
QLabel *smallLab = new QLabel;
QLabel *textLab = new QLabel("Two");
bigLab->setPixmap(big);
smallLab->setPixmap(small);
QHBoxLayout *hLay = new QHBoxLayout;
hLay->addWidget(bigLab);
hLay->addWidget(textLab);
QHBoxLayout *vLay = new QHBoxLayout;
vLay->addWidget(smallLab,0,Qt::AlignRight);
box->addLayout(hLay);
box->addLayout(vLay);
window->setLayout(box);
window->show();
Result:
What I normally do is:
Design the layout with Qt Designer/Creator using rich features of layouting.
Set its instances (from code) as the item widget of a list or table widget.
Be careful, If the item count of the list is too large, it will perform very slowly.
P.S. If you really need the layout coded, just use the code generated by Qt designer.

Qt: How to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side?

I would like to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side.
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
PS: I tried using addWidget() to add to the left and addPermanentWidget() to add to the right but it doesn't look neat and also it doesn't feel right.
You can add two buttons to a layout in a widget and add the widget to the status bar using QStatusBar::addWidget :
QWidget * widget = new QWidget();
QPushButton * leftBut = new QPushButton("Left");
QPushButton * rightBut = new QPushButton("Right");
QGridLayout * layout = new QGridLayout(widget);
layout->addWidget(leftBut,0,0,1,1,Qt::AlignVCenter | Qt::AlignLeft);
layout->addWidget(rightBut,0,1,1,1,Qt::AlignVCenter | Qt::AlignRight);
ui->statusBar->addWidget(widget,1);
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
Here is a way to use a "fake" spacer.
QPushButton *leftButton = new QPushButton("Left");
QPushButton *rightButton = new QPushButton("Right");
QLabel *spacer = new QLabel(); // fake spacer
ui->statusBar->addPermanentWidget(leftButton);
ui->statusBar->addPermanentWidget(spacer, 1);
ui->statusBar->addPermanentWidget(rightButton);
The second parameter in addPermanentWidget is "used to compute a suitable size for the given widget as the status bar grows and shrinks".
Demo:
I think the simplest way is using a QGridLayout (honestly I never tried to modify a status bar anyway) supposing that the status bar is or descends from widget you can do this:
QGridLayout *myGridLayout = new QGridLayout();
statusbar->setLayout(myGridLayout)
QPushButton *button1 = new QPushButton(this);
myGridLayout->addWidget(button1,0,0,1,1);
QPushButton *button2 = new QPushButton(this);
myGridLayout->addWidget(button2,X,0,1,1);
The biggest is X the more space you want to leave in between, I would suggest to start with 3 and then make few tests to see how it looks.

Generate checkbox on the fly

I've got a dynamically created list of image extensions that I want to display checkboxes for.
I have a QStringList that contains .png, .jpg, .bmp. This list can be altered by the user so I need to generate a checkbox on the UI for each possibility.
QStringList filters;
filters << "*.jpg" << "*.png" << "*.jpeg";
I was thinking about a foreach or for loop to achieve this.
foreach(QString filt, filters){
QCheckBox *checkbox = new QCheckBox(filt, this);
}
This puts 3 checkboxes on the UI but they are all on top of one another.
How can I space them and also, how can I work with the change in state from check to unchecked on the fly?
Absolutely lost about how to do this when it's generating checkboxes from a stringlist.
Thanks.
The checkboxes are stacking on top of one another because you are not adding them to the widget's layout. Here's an example that will put each checkbox into a vertical layout.
QWidget *w = new QWidget;
QVBoxLayout *vbox = new QVBoxLayout;
foreach(QString filt, filters){
QCheckBox *checkbox = new QCheckBox(filt, this);
checkbox->setChecked(true);
vbox->addWidget(checkbox);
}
w->setLayout(vbox);
w->show()
Read up on QVBoxLayout at http://qt-project.org/doc/qt-5.0/qtwidgets/qvboxlayout.html

Is it possible to partially italicize the text of a QTreeWidgetItem?

I know how to italicize the entire text of a QTreeWidgetItem:
QTreeWidgetItem* elt = new QTreeWidgetItem(item);
QFont font = elt->font(0);
font.setItalic(true);
elt->setText(0, choice);
elt->setFont(0, font);
But is it possible to italicize only part of that text? (e.g. the first one or two words)
It's possible with:
QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
QLabel *label = new QLabel("<i>italics</i>, <b>bold</b>, normal", treeWidget);
treeWidget->setItemWidget(item, 0, label);
but cleaner solution could be by using QTreeView and subclassing QItemDelegate.
There is no such option by default. You need to set a QItemDelegate that is able to render HTML. See this solution.