QStandardItemModel inside Qtableview - qt

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.

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::scrollTo() (finding the right QModelIndex)

I'm trying to get PgDown clicks on a QTableView to scroll down a variable number of rows. I talk to my subclassed QSortFilterProxyModel which talks to the subclassed QAbstractTableModel to figure out what the next row is. That's all fine and dandy but I believe I'm faced with two caveats:
1: The row number inside the view doesn't do much. I need a QPoint on the screen to scroll to, and I'm not sure how to derive that from a cell.
2: I can create an index in the QSortFilterProxyModel but this generally causes crashes, as the parent is different... or I'm missing something.
int nextRow = getModel()->nextRow( indexAt( rect().topLeft() ) );
QModelIndex nextIndex = getModel()->index( nextRow, 0 );
scrollTo( nextIndex, QAbstractItemView::PositionAtTop );
Okay, I figured this out:
QModelIndex nextIndex = getModel()->index( nextRow, 0 );
scrollTo( nextIndex, QAbstractItemView::PositionAtTop );
I was having the QSortFilterProxyModel create and index which was a big no-no. I have issues when I have hidden rows, but should hopefully be able to figure that out.

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);
}
}

QTableWidget edit only one column and leave the rest non-editable

In QT 4.7, I am trying to make one QTableWidgetItem in a QTableWidget Editable and the rest all columns should be read only for me. I am having problems here.
I have checked a number of samples through google and stackoverflow but failed to achieve this. Some of the options I tried are,
I create rows by calling insertRow(rownumber) for adding rows.
Trial 1: I do the following while inserting a row dynamically
Enable Edit triggers in the UI Dialog
Add columns using the following code for disabling edit
QTableWidgetItem qit("");
qit.setflags(qit.flags() & ~Qt::ItemIsEditable)
qtable.setitem(row,column, &qit);
And for others columns I don't set the flags
This above approach did not work. I am able edit all columns (even the one I negated the editable option)
Trial 2:
Do all the above with just qtable.setEditTriggers(Qt::NoEditTriggers) and then set the columns editable wherever required.
But this option renders all columns non-editable.
But I don't see anyone complaining like this in any forums. So I must be making some stupid mistake.
Have someone come across such an issue, if yes please help by answering.
Working example of QTableWidget
First item in added row is editable, second one is not editable.
#include <QtGui>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Prepare layout
QMainWindow *window = new QMainWindow;
QTableWidget *tablewidget = new QTableWidget;
window->setCentralWidget(tablewidget);
// Add data
tablewidget->insertRow(0);
tablewidget->insertColumn(0);
tablewidget->insertColumn(1);
QTableWidgetItem *item;
item = new QTableWidgetItem("editable");
tablewidget->setItem(0,0,item);
item = new QTableWidgetItem("non editable");
item->setFlags(item->flags() & ~Qt::ItemIsEditable); // non editable
tablewidget->setItem(0,1,item);
window->show();
return a.exec();
}

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

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.

Resources