Make QHeaderView/QTableView-Header interactive but keep it stretched to the full available width.
-
Hey guys.
Unfortunately I need to create again create a post here cause the QT discord server seems dead. All of my questions there are never answered or somebody even cared :/ Would be way faster but I cant change it.. Sad times.Anyway my problem:
I want my QHeaderView to stretch to the full available width but without losing the interactive part. I want that the user can still resize the columns. For that I tried to set the section resize mode to Interactive and then resize each column once (except the last one so the user cant stretch it out of bounds):header->setSectionResizeMode(QHeaderView::Interactive); for (int i = 0; i < model->rowCount(); i++) header->resizeSection(i, QHeaderView::Stretch); header->setStretchLastSection(true);
But the outcome is unchanged. It seems like "resizeSection" doesnt work. It doesnt matter if I remove thesetStretchLastSection(true)
, remove theheader->setSectionResizeMode(QHeaderView::Interactive);
or even give it a specific sizeheader->resizeSection(i, 500);
.
I tried multiple variations but theresizeSection
never had any effect.So does anybody have an idea what is wrong with
resizeSection
or what could probably be the solution?Thanks guys <3
-
@JonB I cant find the source anymore but it was a qt-forum or stackoverflow post where somebody had the same issue. Somebody used it there so I tried it and neither my compiler nor my intellisense returned an error so I thought there is a function like this. Seems like there isnt.
But like I said I triedresizeSection(i, 500)
orresizeSection(0, 500)
too without any changes.@VogelPapaFinn
SinceQHeaderView::Stretch == 1
I think, using that as per your code would actually make them all minimum width which is exactly what you don't want, right? So it's important :)My next thought is you are setting those widths on a
QHeaderView
while it isn't attached to any model/has any columns. I simply don't know whether that is an issue.Try
qDebug() << header->count()
immediately after your loop: what does it return?Try moving the lines setting the section widths to just before the
view->show();
?Finally, since we are trying to understand what is going on comment out the
hideSection()
s, maybe they affect behaviour.Depending on answers, might have to move to
showEvent()
but we'll see. -
Hey guys.
Unfortunately I need to create again create a post here cause the QT discord server seems dead. All of my questions there are never answered or somebody even cared :/ Would be way faster but I cant change it.. Sad times.Anyway my problem:
I want my QHeaderView to stretch to the full available width but without losing the interactive part. I want that the user can still resize the columns. For that I tried to set the section resize mode to Interactive and then resize each column once (except the last one so the user cant stretch it out of bounds):header->setSectionResizeMode(QHeaderView::Interactive); for (int i = 0; i < model->rowCount(); i++) header->resizeSection(i, QHeaderView::Stretch); header->setStretchLastSection(true);
But the outcome is unchanged. It seems like "resizeSection" doesnt work. It doesnt matter if I remove thesetStretchLastSection(true)
, remove theheader->setSectionResizeMode(QHeaderView::Interactive);
or even give it a specific sizeheader->resizeSection(i, 500);
.
I tried multiple variations but theresizeSection
never had any effect.So does anybody have an idea what is wrong with
resizeSection
or what could probably be the solution?Thanks guys <3
@VogelPapaFinn said in Make QHeaderView interactive but keep it stretched to the full available width.:
header->resizeSection(i, QHeaderView::Stretch);
I don't see any overload of QHeaderView::resizeSection() which should accept a QHeaderView::ResizeMode like
QHeaderView::Stretch
.If this is a horizontal header (I presume it is, because it shows column names), how would
for (int i = 0; i < model->rowCount(); i++) header->resizeSection...
make any sense? Why would you iterate rows to address vertical column headers, and don't you think
model->rowCount()
will be 0 so this won't execute anyway? -
Ops that was a mistake there. Just rewrote the code because I deleted it. But this is not the fault Im talking about. Calling
header->resizeSection(0, 500)
directly for example doesnt change anything.
So yes here I made stupid mistake but that is not the one causing trouble. -
Ops that was a mistake there. Just rewrote the code because I deleted it. But this is not the fault Im talking about. Calling
header->resizeSection(0, 500)
directly for example doesnt change anything.
So yes here I made stupid mistake but that is not the one causing trouble.@VogelPapaFinn said in Make QHeaderView interactive but keep it stretched to the full available width.:
Calling header->resizeSection(0, 500) directly for example doesnt change anything.
@JonB said in Make QHeaderView interactive but keep it stretched to the full available width.:
If this is a horizontal header (I presume it is, because it shows column names), how would
for (int i = 0; i < model->rowCount(); i++) header->resizeSection...
make any sense? Why would you iterate rows to address vertical column headers, and don't you think model->rowCount() will be 0 so this won't execute anyway?
-
@VogelPapaFinn said in Make QHeaderView interactive but keep it stretched to the full available width.:
Calling header->resizeSection(0, 500) directly for example doesnt change anything.
@JonB said in Make QHeaderView interactive but keep it stretched to the full available width.:
If this is a horizontal header (I presume it is, because it shows column names), how would
for (int i = 0; i < model->rowCount(); i++) header->resizeSection...
make any sense? Why would you iterate rows to address vertical column headers, and don't you think model->rowCount() will be 0 so this won't execute anyway?
@JonB what do you want to say with that? I made a mistake at "counting" but that doesnt matter. Thw function does not work at all.
-
@JonB what do you want to say with that? I made a mistake at "counting" but that doesnt matter. Thw function does not work at all.
@VogelPapaFinn
So you want to know what is wrong with your code, but you don't want to show what you actually have, right? I should not point out that the code you have shown does not actually call the function you talk about? So I should guess what you have or have changed to, and that it's correct now? Great.I would start by putting in at least one row of data to see what it looks like. And I would play around with your resize calls before versus after there is some data shown in the table in case that changes behaviour, I don't know. I would also put a
qDebug()
into the loop so that I knew theresizeSection()
gets called on the right columns at the time it is called. -
@VogelPapaFinn
So you want to know what is wrong with your code, but you don't want to show what you actually have, right? I should not point out that the code you have shown does not actually call the function you talk about? So I should guess what you have or have changed to, and that it's correct now? Great.I would start by putting in at least one row of data to see what it looks like. And I would play around with your resize calls before versus after there is some data shown in the table in case that changes behaviour, I don't know. I would also put a
qDebug()
into the loop so that I knew theresizeSection()
gets called on the right columns at the time it is called.@JonB ehm. The function im talking about is in that code snippet I send you?! Its in the for loop so I dont know why you are not understanding my problem.
The code is just a simple example to show what Im talking about and one of the things I tried. But the function does not work at all: If you call it with a specific column index (for example 1) still nothing happens. With or without data doesnt matter. So i really dont understand what you expect me to do now. Im just searching for a different approach (with different functions etc.) or an idea/solution why the function is not working.
-
And you still use rowCount() when trying to resize the horizontal header?
-
And you still use rowCount() when trying to resize the horizontal header?
@Christian-Ehrlicher nope I dont. Why are you all so focused on the row Count?! Its a simple mistake I ONLY did in the post! The problem is NOT this for loop it is the function that is NOT working. If I remove the loop and hardcode it, it still DONT work.
Again: the functionresizeSection()
has no effect no matter how I use it. -
You don't post useful code but blame us? Nice...
Post what you're doing and where. resizeColumn() works as expected. resizeColumn() inside resizeEvent() may work but it must not. -
You don't post useful code but blame us? Nice...
Post what you're doing and where. resizeColumn() works as expected. resizeColumn() inside resizeEvent() may work but it must not.@Christian-Ehrlicher Im not blaming anyone Im just confused why you two are still asking about the row issue.
What code do you want exactly? Every single thing I tried? Or my complete class?Im going to send you a complete rewritten problem description maybe we can then solve it together.
// TESTING QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); db.setHostName("127.0.0.1"); db.setDatabaseName("bugtracker"); db.setUserName("postgres"); db.setPassword("CENSORED"); db.open(); QSqlTableModel* model = new QSqlTableModel; model->setTable("account"); model->setEditStrategy(QSqlTableModel::OnFieldChange); model->select(); QFont font("Segoe UI", 8, -1, false); font.setBold(true); QHeaderView* header = new QHeaderView(Qt::Horizontal); header->setSectionResizeMode(QHeaderView::Interactive); for (int i = 0; i < model->columnCount(); i++) header->resizeSection(i, QHeaderView::Stretch); header->setStretchLastSection(true); header->setDefaultAlignment(Qt::AlignVCenter); header->setStyleSheet("QHeaderView::section{background-color: #D9D9D9; border: none; border-top: 1px solid #999997; border-bottom: 1px solid #999997; border-right: 1px dashed #999997; padding-left: 3px;}"); header->setFont(font); QTableView* view = findChild<QTableView*>("table_view"); view->setModel(model); view->verticalHeader()->hide(); view->setHorizontalHeader(header); view->horizontalHeader()->hideSection(0); view->horizontalHeader()->hideSection(4); view->horizontalHeader()->hideSection(5); view->horizontalHeader()->hideSection(6); view->horizontalHeader()->hideSection(9); view->show(); // TESTING
This is what the code for the QTableView + Header looks like rn. Its dirty I know. Im still testing it before I clean it up.
This is how the Header/Table looks right now. But what I want is this:
Unfortunately you cant see the cursor here. I want that the columns are still resizable with the mouse. The same thing you can do for example in Excel. But there is no
QHeaderView::ResizeMode
that supports stretch and interactive at once.Did this help?
-
@Christian-Ehrlicher Im not blaming anyone Im just confused why you two are still asking about the row issue.
What code do you want exactly? Every single thing I tried? Or my complete class?Im going to send you a complete rewritten problem description maybe we can then solve it together.
// TESTING QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); db.setHostName("127.0.0.1"); db.setDatabaseName("bugtracker"); db.setUserName("postgres"); db.setPassword("CENSORED"); db.open(); QSqlTableModel* model = new QSqlTableModel; model->setTable("account"); model->setEditStrategy(QSqlTableModel::OnFieldChange); model->select(); QFont font("Segoe UI", 8, -1, false); font.setBold(true); QHeaderView* header = new QHeaderView(Qt::Horizontal); header->setSectionResizeMode(QHeaderView::Interactive); for (int i = 0; i < model->columnCount(); i++) header->resizeSection(i, QHeaderView::Stretch); header->setStretchLastSection(true); header->setDefaultAlignment(Qt::AlignVCenter); header->setStyleSheet("QHeaderView::section{background-color: #D9D9D9; border: none; border-top: 1px solid #999997; border-bottom: 1px solid #999997; border-right: 1px dashed #999997; padding-left: 3px;}"); header->setFont(font); QTableView* view = findChild<QTableView*>("table_view"); view->setModel(model); view->verticalHeader()->hide(); view->setHorizontalHeader(header); view->horizontalHeader()->hideSection(0); view->horizontalHeader()->hideSection(4); view->horizontalHeader()->hideSection(5); view->horizontalHeader()->hideSection(6); view->horizontalHeader()->hideSection(9); view->show(); // TESTING
This is what the code for the QTableView + Header looks like rn. Its dirty I know. Im still testing it before I clean it up.
This is how the Header/Table looks right now. But what I want is this:
Unfortunately you cant see the cursor here. I want that the columns are still resizable with the mouse. The same thing you can do for example in Excel. But there is no
QHeaderView::ResizeMode
that supports stretch and interactive at once.Did this help?
@VogelPapaFinn said in Make QHeaderView interactive but keep it stretched to the full available width.:
for (int i = 0; i < model->columnCount(); i++) header->resizeSection(i, QHeaderView::Stretch);
I asked you before about the
header->resizeSection(i, QHeaderView::Stretch);
you use:I don't see any overload of QHeaderView::resizeSection() which should accept a QHeaderView::ResizeMode like
QHeaderView::Stretch
.Could you explain this to me? Thanks.
-
@VogelPapaFinn said in Make QHeaderView interactive but keep it stretched to the full available width.:
for (int i = 0; i < model->columnCount(); i++) header->resizeSection(i, QHeaderView::Stretch);
I asked you before about the
header->resizeSection(i, QHeaderView::Stretch);
you use:I don't see any overload of QHeaderView::resizeSection() which should accept a QHeaderView::ResizeMode like
QHeaderView::Stretch
.Could you explain this to me? Thanks.
@JonB I cant find the source anymore but it was a qt-forum or stackoverflow post where somebody had the same issue. Somebody used it there so I tried it and neither my compiler nor my intellisense returned an error so I thought there is a function like this. Seems like there isnt.
But like I said I triedresizeSection(i, 500)
orresizeSection(0, 500)
too without any changes. -
@JonB I cant find the source anymore but it was a qt-forum or stackoverflow post where somebody had the same issue. Somebody used it there so I tried it and neither my compiler nor my intellisense returned an error so I thought there is a function like this. Seems like there isnt.
But like I said I triedresizeSection(i, 500)
orresizeSection(0, 500)
too without any changes.@VogelPapaFinn
SinceQHeaderView::Stretch == 1
I think, using that as per your code would actually make them all minimum width which is exactly what you don't want, right? So it's important :)My next thought is you are setting those widths on a
QHeaderView
while it isn't attached to any model/has any columns. I simply don't know whether that is an issue.Try
qDebug() << header->count()
immediately after your loop: what does it return?Try moving the lines setting the section widths to just before the
view->show();
?Finally, since we are trying to understand what is going on comment out the
hideSection()
s, maybe they affect behaviour.Depending on answers, might have to move to
showEvent()
but we'll see. -
@VogelPapaFinn
SinceQHeaderView::Stretch == 1
I think, using that as per your code would actually make them all minimum width which is exactly what you don't want, right? So it's important :)My next thought is you are setting those widths on a
QHeaderView
while it isn't attached to any model/has any columns. I simply don't know whether that is an issue.Try
qDebug() << header->count()
immediately after your loop: what does it return?Try moving the lines setting the section widths to just before the
view->show();
?Finally, since we are trying to understand what is going on comment out the
hideSection()
s, maybe they affect behaviour.Depending on answers, might have to move to
showEvent()
but we'll see.@JonB Okay it seems like the unattached model was the problem. It now starts to work, yey. Now I just need to resize the columns correctly. I tried to calculate the size by doing this:
header->setSectionResizeMode(QHeaderView::Interactive); for (int i = 0; i < model->columnCount(); i++) header->resizeSection(i, view->width() / model->columnCount()); header->setStretchLastSection(true);
Result:
The problem here is thatview->width()
returns only 98 [pixels]. Removingheader->setStretchLastSection(true);
only decreases the width of the last section. So it does not affect the other sections. Its size policy is set to stretch and in the editor and when the app starts it fills the whole space (way more than 98 pixels). Any idea what is causing this? -
Since the size of a widget is first known when the widget is shwon you have to do your resizing after the show event.
-
Since the size of a widget is first known when the widget is shwon you have to do your resizing after the show event.
This post is deleted! -
@Christian-Ehrlicher It now finaly works. Yeehaaw. I needed to reimplement the resizeFunction or otherwise they get resized before the window gets maximized > they are too small.
Im going to clean up the code rn and provide a complete description of the solution for people in the future with the same issue. Thanks to you two <3 -
Okay guys so this is my final code. If you here because of the same problem then this is for you.
- First we need to create all necessary objects:
- QSqlDatabase [only needed if you want to use it with a db],
- QSqlTableModel [you can use other models ofc],
- QTableView
Here is my code. This code snippet is in the constructor of my class
UserSite
. You can ignore my specific settings like the Font or the removeColumn calls.
ATTENTION:db_ = fbt::SqlConnection::getInstance();
This line of code uses a self-written class which handles the sql connections. You can replace this line of code with the usual db connection initialization.// Establish SQL Connection db_ = fbt::SqlConnection::getInstance(); // Create Table Model sql_model_ = new QSqlTableModel; sql_model_->setTable("account"); sql_model_->setEditStrategy(QSqlTableModel::OnFieldChange); // Edits the database when a cell is edited by the user sql_model_->select(); sql_model_->removeColumn(0); // Removes account_id sql_model_->removeColumn(3); // Removes password sql_model_->removeColumn(3); // Removes location sql_model_->removeColumn(3); // Removes birth sql_model_->removeColumn(5); // Removes created // Temporary saved font to use in the header QFont font("Segoe UI", 8, -1, false); font.setBold(true); // Create Table View table_view_ = findChild<QTableView*>("table_view"); table_view_->setModel(sql_model_); table_view_->verticalHeader()->hide(); table_view_->show(); // Style header of the Table View tv_header_ = table_view_->horizontalHeader(); tv_header_->setSectionResizeMode(QHeaderView::Interactive); // Let the user resize the columns tv_header_->setDefaultAlignment(Qt::AlignVCenter); // Aligns the header text to the left tv_header_->setStyleSheet("QHeaderView::section{background-color: #D9D9D9; border: none; border-top: 1px solid #999997; border-bottom: 1px solid #999997; border-right: 1px dashed #999997; padding-left: 3px;}"); tv_header_->setFont(font);
- Now to the second and important part: the
resizeEvent(QResizeEvent* event)
function. We need to implement this so the columns get resized everytime the window itself gets resized. This is important because of two reasons:
1 - When we initialize the QTableView the QHeaderView etc. the window isnt open yet (at least this is the case in my code). This is bad because the QTableView doesnt know its size and we cant resize the columns properly.
2 - When the user resizes the whole window a scrollbar will appear at the bottom because every column keeps their size. I dont want this so its a win-win. If you dont want this then you need to find a way around that. Good luck then!
Enough text. Here is the code of the
resizeEvent()
function:void UserSite::resizeEvent(QResizeEvent* event) { // Resize columns manually - this is to keep the columns stretched but resizable for the user for (int i = 0; i < sql_model_->columnCount(); i++) tv_header_->resizeSection(i, table_view_->width() / sql_model_->columnCount()); // This resizes every column to the same size // Sets the ResizeMode of the last column to stretched so that the user can resize it. Otherwise the user can move it out of the max width and the scrollbar appears. table_view_->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch); // Handle everything else QWidget::resizeEvent(event); }
Now you should have a working QTableView header that is resizable by the user but stretched at the same time. If this didnt work or you have a problem feel free to reopen this thread or send me a private message. You can do this here in the forum or on Discord: VogelPapa | Finn#0442
Have a nice day <3// Edit: Just realized, thanks to @Christian-Ehrlicher that you dont need a "new" QHeaderView because the QTableView already has one. I changed the code slightly so but it works the same way.
- First we need to create all necessary objects:
-
Okay guys so this is my final code. If you here because of the same problem then this is for you.
- First we need to create all necessary objects:
- QSqlDatabase [only needed if you want to use it with a db],
- QSqlTableModel [you can use other models ofc],
- QTableView
Here is my code. This code snippet is in the constructor of my class
UserSite
. You can ignore my specific settings like the Font or the removeColumn calls.
ATTENTION:db_ = fbt::SqlConnection::getInstance();
This line of code uses a self-written class which handles the sql connections. You can replace this line of code with the usual db connection initialization.// Establish SQL Connection db_ = fbt::SqlConnection::getInstance(); // Create Table Model sql_model_ = new QSqlTableModel; sql_model_->setTable("account"); sql_model_->setEditStrategy(QSqlTableModel::OnFieldChange); // Edits the database when a cell is edited by the user sql_model_->select(); sql_model_->removeColumn(0); // Removes account_id sql_model_->removeColumn(3); // Removes password sql_model_->removeColumn(3); // Removes location sql_model_->removeColumn(3); // Removes birth sql_model_->removeColumn(5); // Removes created // Temporary saved font to use in the header QFont font("Segoe UI", 8, -1, false); font.setBold(true); // Create Table View table_view_ = findChild<QTableView*>("table_view"); table_view_->setModel(sql_model_); table_view_->verticalHeader()->hide(); table_view_->show(); // Style header of the Table View tv_header_ = table_view_->horizontalHeader(); tv_header_->setSectionResizeMode(QHeaderView::Interactive); // Let the user resize the columns tv_header_->setDefaultAlignment(Qt::AlignVCenter); // Aligns the header text to the left tv_header_->setStyleSheet("QHeaderView::section{background-color: #D9D9D9; border: none; border-top: 1px solid #999997; border-bottom: 1px solid #999997; border-right: 1px dashed #999997; padding-left: 3px;}"); tv_header_->setFont(font);
- Now to the second and important part: the
resizeEvent(QResizeEvent* event)
function. We need to implement this so the columns get resized everytime the window itself gets resized. This is important because of two reasons:
1 - When we initialize the QTableView the QHeaderView etc. the window isnt open yet (at least this is the case in my code). This is bad because the QTableView doesnt know its size and we cant resize the columns properly.
2 - When the user resizes the whole window a scrollbar will appear at the bottom because every column keeps their size. I dont want this so its a win-win. If you dont want this then you need to find a way around that. Good luck then!
Enough text. Here is the code of the
resizeEvent()
function:void UserSite::resizeEvent(QResizeEvent* event) { // Resize columns manually - this is to keep the columns stretched but resizable for the user for (int i = 0; i < sql_model_->columnCount(); i++) tv_header_->resizeSection(i, table_view_->width() / sql_model_->columnCount()); // This resizes every column to the same size // Sets the ResizeMode of the last column to stretched so that the user can resize it. Otherwise the user can move it out of the max width and the scrollbar appears. table_view_->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch); // Handle everything else QWidget::resizeEvent(event); }
Now you should have a working QTableView header that is resizable by the user but stretched at the same time. If this didnt work or you have a problem feel free to reopen this thread or send me a private message. You can do this here in the forum or on Discord: VogelPapa | Finn#0442
Have a nice day <3// Edit: Just realized, thanks to @Christian-Ehrlicher that you dont need a "new" QHeaderView because the QTableView already has one. I changed the code slightly so but it works the same way.
@VogelPapaFinn said in Make QHeaderView interactive but keep it stretched to the full available width.:
tv_header_ = new QHeaderView(Qt::Horizontal); tv_header_->setModel(sql_model_);
This is not needed, every view has a header.
- First we need to create all necessary objects: