How to set font Bold to a particular row in table widget - qt

i want to set my font as bold in particular row column position of my tablewidget.
I did like this but getting break.
QFont font("Helvetica", 12, QFont::Bold);
overviewTable->item(2,2)->setFont(font);
Please Help

I think everything is ok. Here what docs said:
void QTableWidgetItem::setFont ( const QFont & font )
Sets the font used to display the item's text to the given font.
Maybe your overviewTable const?
ADDED:
This variant works fine for my Qt 4.6:
tableWidget = new QTableWidget(12, 3, this);
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 3; j++) {
QTableWidgetItem *newItem = new QTableWidgetItem(tr("%1").arg(
(i+1)*(j+1)));
tableWidget->setItem(i, j, newItem);
}
}
QFont font;
font.setBold(true);
tableWidget->item(2, 2)->setFont(font);

Maybe you are getting break because you didn't call setItem() to set an item for the cell (2, 2) before you use overviewTable->item(2,2). As the Qt document says,
QTableWidgetItem * QTableWidget::item(int row, int column) const
Returns the item for the given row and column if one has been set;
otherwise returns 0.
That is, your overviewTable->item(2,2) probably returns 0, thus causes a Segmentation fault in the setFont() call.
So your means to setting font is completely right. You just need to call setItem() at first as mosg's answer suggests.
ADDED:
if your overviewTable is a QTableWidget created in Qt Designer, then in the Designer a double-click on a cell (just to enter its editing mode, no need to actually enter anything) will have the effect of calling setItem() for that cell. Later in your code you can directly using the item() function without having to call setItem() first.

Related

Can a QComboBox display a different value than whats in it's list?

Using Qt 5.9 on Linux, I have a QComboBox with several labels.
qc = new QComboBox;
qc->addItem(tr("Red"));
qc->addItem(tr("Green"));
qc->addItem(tr("Blue"));
Lets say a user activates the QComboBox and the 3 color labels are shown in the drop down list. The user then selects the 1st item (red).
What I want to do is have the QComboBox display a different value than what was selected. I.e., if red is selected, then a number is shown, possibly 1 for the first item (or it could be an R for Red), and if green is selected, then display 2 (or G) for the second item.
My goal in doing this is to use less display space (less wide) than is actually necessary to show the complete text of the selection because some of my item strings are quite long and a much shorter label is desired when the QComboBox is not activated in it's drop down state. Besides, the item strings are descriptive and abbreviations would work better for displaying.
Edit:
Using Marek's example, thought this might help. Here's what I have. I'm expecting if the user selects from the list, then an R, G, or a B should be displayed after.
QStandardItem *red = new QStandardItem();
red->setData(tr("Red"), Qt::DisplayRole);
red->setData("R", Qt::UserRole);
QStandardItem *green = new QStandardItem();
green->setData(tr("Green"), Qt::DisplayRole);
green->setData("G", Qt::UserRole);
QStandardItem *blue = new QStandardItem();
blue->setData(tr("Blue"), Qt::DisplayRole);
blue->setData("B", Qt::UserRole);
QStandardItemModel *rgb_model = new QStandardItemModel(this);
rgb_model->setItem(0, red);
rgb_model->setItem(1, green);
rgb_model->setItem(2, blue);
QComboBox *rgb_cb = new QComboBox();
rgb_cb->setModel(rgb_model);
I get the feeling it's because I don't quite understand how to use Qt::UserRole.
Yes it is possible. QComboBox uses data model to manage items.
You have to provide own data model, with items with respective data values.
QStandardItem *itme1 = new QStandardItem();
item1->setData(tr("Red"), Qt::DisplayRole);
item1->setData("1", Qt::UserRole); // note doesn't have to be a string.
QStandardItem *itme2 = new QStandardItem();
item2->setData(tr("Green"), Qt::DisplayRole);
item2->setData("2", Qt::UserRole);
QStandardItemModel *model = new QStandardItemModel(this);
mode->setItem(1, item1);
mode->setItem(2, item2);
qc->setModel(model);
It should work, but I didn't test it. At least this should be some clue.
Please review QComboBox documentation, especially about roles.
Another solution is use translations with multiple lengths. You can provide couple translation for a single string. Each translation should be graphically shorter than earlier one.
In such situation QString contains all possibilities separated by spatial character. When such string is rendered first substring (between separators) which will fit available space will be used.
Now I do not remember what is the separator value. I've used this very long time ago (with Qt 4.8) and now can't find reference for it.
In your example for make it short just make:
qc->setWidth( 20 );
But if you really want user choose something, then:
connect( qc, SIGNAL( onCurrentIndexChanged( int ) ), SLOT( changeComboText() ) );
[...]
void changeComboText()
{
QString shortText;
//Determine short value for shortText
qc->setCurrentText( shortText );
}

QTableView scrolling stopped after dynamic resizing

I have a QTableView with a custom QSortFilterProxyModel for searching and sorting and a QSqlQueryModel for populating the table.
void ProxyModel::searchTable(QString name, QString type, QString date, QString time ){
if(name_ != name)
name_ = name;
if(type_ != type)
type_ = type;
if(date_ != date)
date_ = date;
if(time_ != time)
time_ = time;
invalidateFilter();
}
bool ProxyModel::filterAcceptsRow(int source_row,
const QModelIndex &source_parent) const{
QModelIndex indName = sourceModel()->index(source_row,
0, source_parent);
QModelIndex indType= sourceModel()->index(source_row,
4, source_parent);
QModelIndex indDate = sourceModel()->index(source_row,
2, source_parent);
QModelIndex indTime = sourceModel()->index(source_row,
3, source_parent);
if(
sourceModel()->data(indName).toString().toLower().contains(name_.toLower())
&&sourceModel()->data(indType).toString().toLower().contains(type_.toLower())
&&sourceModel()->data(indDate).toString().toLower().contains(date_.toLower())
&&sourceModel()->data(indTime).toString().toLower().contains(time_.toLower())
)
{
emit adjust();
return true;
}
return false;
}
After a successful search, I emit a signal from my proxy model to a slot where it adjusts the table height to fit the size of the rows.
connect(proxyModel, SIGNAL(adjust()), this, SLOT(dataChanged()));
And when the search button is clicked
connect(ui->searchBtn, &QToolButton::clicked, this, &AllVisitedPlaces::getSearchOptions);
I call the proxy model searchTable method with search parameters
void AllVisitedPlaces::getSearchOptions()
{
proxyModel->searchTable(ui->nameLineEdit->text(),
ui->typeLineEdit->text(),
ui->dateLineEdit->text(),
ui->timeLineEdit->text());
adjustTableSize();
}
void AllVisitedPlaces::dataChanged()
{
adjustTableSize();
this->verticalHeader->setSectionResizeMode(QHeaderView::ResizeToContents);
}
void AllVisitedPlaces::adjustTableSize()
{
QRect rect = ui->table->geometry();
int height = 0;
for (int i =0; i < proxyModel->rowCount() ; i++)
height+= ui->table->rowHeight(i);
rect.setHeight(18 + ui->table->horizontalHeader()->height() + height);
ui->table->setGeometry(rect);
verticalHeader->setSectionResizeMode(QHeaderView::Stretch);
}
The problem is, when the table re-sizes , I lose scrolling.
How can I fix that ?
Before re-sizing :
After re-sizing :
Why would you expect scrolling when you've resized the table to fit its contents?
The likely problem is that your Ui is broken in other ways and the table is obscured: it has been resized, but you can't see that because whatever widget the table view sits in doesn't manage the table widget properly. But we can't tell for sure because you didn't minimize your code to provide a complete compileable example of what you're doing. We're talking about <100 lines of code in all - surely it wouldn't be a big deal to just paste such a main.cpp in your question. See e.g. example 1 or example 2.
This is a bad design anyway since you're presuming that the table will fit on screen. Yet it won't: once the resizing works, you'll end up with a vertically huge window that cannot be used as some of its corners will extend past the screen, with no way to reach them to see the contents or to resize the window.
Finally, once you properly use layouts in your Ui design, the setGeometry() call on any widget below top-level is a no-op: it's the layout that controls the child widget geometry. The solution then is not to set the widget's geometry, but to set its minimum size instead.
You're facing an XY Problem: you're dead set on a solution, without telling us what it is that you're trying to achieve and making sure first that what you're after makes sense (as in: that it will actually lead to a usable Ui!).

QTableWidget memory leak or not?

Suppose I have a 2D array full of data say 10 x 10. The contents, as well as a number of rows, can change any time.
Now I want to display this data in a QTableWidget.
I use a timer with time out 1sec to refresh the table contents. In the timeout slot if I use
void slot_timeOut()
{
//Iterate over the rows
//and for each cell do something like
ui->tw_data->setItem(row, 0, new TableWidgetItem(data[row][0]);
ui->tw_data->setItem(row, 0, new TableWidgetItem(data[row][1]);
//...
ui->tw_data->setItem(row, 0, new TableWidgetItem(data[row][9]);
}
the use out new TableWidgetItem worries me. I have no reference to it and I never delete it.
Over a period of time is this a memory leak, or is this managed by Qt, pls help...
There is no leak, as
The table takes ownership of the item.
(From QTableWidget::setItem()).
Ownership here means that the QTableWidget will take care of deleting the item when its not longer needed, or the QTableWidget itself is destroyed. Ownership is usually documented in the Qt documentation (if not, I'd consider that a Qt bug).
Once setItem() returns from being called on the same cell, the previously set QTableWidgetItem will be deleted:
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QTableWidget widget(2, 1);
QTableWidgetItem* foo = new QTableWidgetItem("Foo");
widget.setItem(0, 0, foo);
qDebug() << foo->text(); //works
widget.setItem(0, 0, new QTableWidgetItem("Bar")); //replaces foo with bar and deletes foo
qDebug() << foo->text(); // Undefined (usually, crash)
widget.show();
return app.exec();
}
If you're on Linux, you can also verify the behavior by running above code (without the second qDebug()) in valgrind with --leak-check=full.
From the Qt documentation:
void QTableWidget::setItem ( int row, int column, QTableWidgetItem *
item ) Sets the item for the given row and column to item. The table
takes ownership of the item.
This indicates that Qt will manage the memory for the object as necessary.
It will delete properly when the you add Q-objects to the cells.
I was pushing thousands of C-strings in cells and watched my memory blow up.
Made my "raw text data" a QString and my problem was solved.
Such problem takes place to be: Qt does not really clear the memory allocated through QTableWidgetItem.
for( int row = 0; row < 35; row++)
{
for(int i = 0; i < 9; i++)
{
QTableWidgetItem* item = new QTableWidgetItem();
item->setText(QString::number(i));
ui->tableWidget->setItem(row, i, item);
}
}
This code gives 116 bytes of leakage.
We found this solution: Instead of QTableWidgetItem, you can use QLineEdit:
QLineEdit* tableline = new QLineEdit();
m_qtablewidget->setCellWidget(row, column, tableline);
p.s. To search for leaks used Dr.memory

Qt How to check state checkbox in QtableWidget

Recently I found the way that checkbox places in the middle of QtableWidget item.
However, I do not know how to check state whether or not button is clicked.
Could you tell me how to check button state?
here is what Ive found code:
QWidget *pWidget = new QWidget();
QCheckBox *pCheckBox = new QCheckBox();
QHBoxLayout *pLayout = new QHBoxLayout(pWidget);
pCheckBox->setCheckState(Qt::Checked);
pLayout->addWidget(pCheckBox);
pLayout->setAlignment(Qt::AlignCenter);
pLayout->setContentsMargins(0,0,0,0);
pWidget->setLayout(pLayout);
ui->tableWidget2->setCellWidget(2,2, pWidget);
Although this is very late you can solve it like this:
auto field = ui->tableWidget2->cellWidget(2, 2, pWidget);
std::cout << qobject_cast<QCheckBox*>(field)->isChecked() << std::endl;
This works for other types as well (QComboBox etc.). Although it would probably be better to just use the checkbox functionality that QTableWidgetItem already has.
This example might not work if you are using a tristate checkbox in which case you should call: checkState() and compare it to Qt::CheckState. If qobject_cast<T> does not work out you can use a reinterpret_cast<T>.
I assume you created your checkboxes in the QWidgetTable like this:
int row...;int column...;
...
QTableWidgetItem *checkBoxItem = new QTableWidgetItem();
checkBoxItem->setCheckState(Qt::Unchecked);
ui->Table->setItem(row, column, checkBoxItem);
You can check the status of the item that corresponds to your widget in another function like this:
void MainWindow::on_Table_cellClicked(int row, int column)
{
QTableWidgetItem *checkBoxState = ui->Table->item(row, column);
if(ui->Table->item(row,column)->checkState())
{
checkBoxState->setCheckState(Qt::Unchecked);
ui->Table->setItem(row, column, checkBoxState);
}
else
{
checkBoxState->setCheckState(Qt::Checked);
ui->Table->setItem(row, column, checkBoxState);
}
}

QStandardItemModel inside Qtableview

I am using QStandardItemModel inside QTableView. Here i have two button & Qtableview inside my mainwindow.
I need only 4 columns inside this. And rows will vary. The two Buttons will be used to add/delete a row (test case).
setHorizontalHeaderItem is not showing all the text(means all text is not visible). Example if i put 'Text for the Employee Name' it is not fully visible ?
How to make QStandardItemModel occupy full QTableview (width). At present it is showing at top left corner ?
How to achieve it?
Code :
model= 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));
model->setItem(row, column, item);
}
}
model->setHorizontalHeaderItem(0, new QStandardItem(tr("Time")));
model->setHorizontalHeaderItem(1, new QStandardItem(tr("Text for the Employee Name")));
model->setHorizontalHeaderItem(2, new QStandardItem(tr("Text for the Employee Address")));
model->setHorizontalHeaderItem(3, new QStandardItem(tr("Text for the Employee Date of Birth")));
model->setVerticalHeaderItem(0, new QStandardItem(tr("Test-Case-----1")));
tableView->horizontalHeader()->setStretchLastSection(true);
or
tableView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
As the question is already accepted for the answer, my answer may help someone, as the above accepted answer didn't help me.
QStandardItemModel *model = new QStandardItemModel(2,3,this);
//----------
ui->tableView->setModel(model);
ui->tableView->resizeColumnsToContents();
I know the answer comes a bit late, but I was just needing to do the same, and figured out a different solution.
To achieve your goal in Qt 4, you need to adjust the settings of the header of your QTableView. To do so, first retrieve the header:
QHeaderView *header = ui->tableView->horizontalHeader();
Next, adjust the resize mode of the individual columns by calling QHeaderView::setResizeMode (the second flavor, which accepts logicalIndex):
header->setResizeMode(0, QHeaderView::ResizeToContents);
header->setResizeMode(1, QHeaderView::ResizeToContents);
header->setResizeMode(2, QHeaderView::ResizeToContents);
header->setResizeMode(3, QHeaderView::Stretch);
In the above example, I chose to stretch column 3, but you may choose any of the columns to be in "stretch" mode.
In Qt 5, the call you want is QHeaderView::setSectionResizeMode().
Hope this helps you or anybody else seeking a solution to this problem.

Resources