Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] QTableWidgetItem::setFont() - how to do it properly
QtWS25 Last Chance

[Solved] QTableWidgetItem::setFont() - how to do it properly

Scheduled Pinned Locked Moved General and Desktop
9 Posts 2 Posters 15.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    d2uriel
    wrote on last edited by
    #1

    Dear Qt programmers,

    Probably a simple question but I haven't found an answer on these forums nor on Google. So here I go.

    I have a QTableWidget object with QTableWidgetItem's inside. I'd like to change selected items font type to what the user selected. Say I have 3 buttons: bold, italic and underline. If I click bold, font in the current cell should change to bold. If I click italic afterwards, it should be bold italic.
    If I do it like this:
    @void myTableEditor::setBold()
    {
    QList<QTableWidgetItem *> list = currentTable()->selectedItems();
    QList<QTableWidgetItem *>::iterator it;
    for(it = list.begin(); it != list.end(); ++it)
    {
    QFont originalFont = (*it)->font();
    originalFont.setBold(true);
    (*it)->setFont(originalFont);
    }
    }@then I cannot retrieve information about this font via
    @(*it)->font().bold();@method. It returns false even if the font was set to bold. I guess it's because I instantiate a QFont object locally in this method and after returning to main event loop it's being destroyed.

    I wanted to do something else:
    @void myTableEditor::setBold()
    {
    QList<QTableWidgetItem *> list = currentTable()->selectedItems();
    QList<QTableWidgetItem *>::iterator it;
    for(it = list.begin(); it != list.end(); ++it)
    {
    QFont *newFont = new QFont((*it)->font());
    newFont->setBold(true);
    (*it)->setFont(*newFont);
    }
    }@but then I don't know what happens when I will set the font to bold a couple of times. Will setFont() destroy the previous QFont object used? Or do I need to take care of it myself? If so, what's the smart way of doing that? Creating a
    @QVector <QVector <QFont *>> fonts;@2D array which will hold pointers to QFont objects for every cell?

    Thank you for your suggestions.

    "Do not judge, and you will never be mistaken." - Jean-Jacques Rousseau

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andre
      wrote on last edited by
      #2

      I think your first way should be the way to go. There is nothing wrong with modifying the current font the way you do. Your second way creates a memory leak.

      I don't immediately spot the error in your first method.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        d2uriel
        wrote on last edited by
        #3

        I didn't exactly explain what's wrong with the first method when I tried using it.

        In a different class I had a slot which was connected to QTableWidget's currentCellChanged() signal. This slot looks like that:
        @void LatTE::updateGUIonCellChange(int currentRow, int currentColumn,
        int previousRow, int previousColumn)
        {
        if(editor->currentTable()->itemAt(currentRow, currentColumn)->font().bold())
        ui.actionBold->setChecked(true);
        else
        ui.actionBold->setChecked(false);

        // .....
        }@and the expression in the if statement always returned false. Even if the actual cell had bold font in it. editor is a pointer to an instance of my class and it's currentTable() method returns a pointer to a QTableWidget object which is currently being visible in the GUI.

        "Do not judge, and you will never be mistaken." - Jean-Jacques Rousseau

        1 Reply Last reply
        0
        • A Offline
          A Offline
          andre
          wrote on last edited by
          #4

          Does the cell render as bold in the table view itself?

          1 Reply Last reply
          0
          • D Offline
            D Offline
            d2uriel
            wrote on last edited by
            #5

            Yes, it does.

            Edit: I've created a 2D array of QFont pointers each pointing to a QFont object for each and every cell in QTableWidget. This works like a charm. I'll try to create a simple project to reproduce this behavior.

            "Do not judge, and you will never be mistaken." - Jean-Jacques Rousseau

            1 Reply Last reply
            0
            • A Offline
              A Offline
              andre
              wrote on last edited by
              #6

              OK, will wait for the example code. If the cell is properly rendered, then the first code block in your first posting is just fine. If you keep having problems reading that value back, instead of creating a whole new array, you may consider using a custom data role and doing something like this:

              Create an enum to create some flags:
              @
              enum FontFlag {Bold = 0x1, Italic = 0x2, Underline = 0x4};
              Q_DECLARE_FLAGS(FontFlags, FontFlag)

              ...
              Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::Options)

              const int FontFlagsRole = Qt::UserRole + 1; //or some other offset
              @

              Then, in your code where you toggle the value, you simply set an instance of this value as a custom data role (using QTableWidgetItem::setData()), and read it back from that role with data().

              @
              void LatTE::updateGUIonCellChange(int currentRow, int currentColumn,
              int previousRow, int previousColumn)
              {
              FontFlags font = FontFlags(editor->currentTable()->itemAt(currentRow, currentColumn)->data(FontFlagsRole).toInt());
              ui.actionBold->setChecked(font.testFlag(Bold));
              ui.actionItalics->setChecked(font.testFlag(Italics));
              ui.actionUnderline->setChecked(font.testFlag(Underline));
              }
              @

              1 Reply Last reply
              0
              • D Offline
                D Offline
                d2uriel
                wrote on last edited by
                #7

                -Sorry, I edited my previous post (added the code). Didn't want to double post. Pleae take a look at it.-

                Here's the test project:

                main.cpp
                @#include "test1.h"
                #include <QtGui/QApplication>

                int main(int argc, char *argv[])
                {
                QApplication a(argc, argv);
                test1 w;
                return a.exec();
                }@
                test1.h
                @#ifndef TEST1_H
                #define TEST1_H

                #include <QtGui>

                class test1 : public QMainWindow
                {
                Q_OBJECT

                public:
                QWidget centralWidget;
                QPushButton *pushButton;
                QTableWidget *tableWidget;

                test1(QWidget *parent = 0, Qt::WFlags flags = 0);
                ~test1();

                public slots:
                void toggleBold();
                void updateButton(int cr, int cc, int pr, int pc);
                };

                #endif // TEST1_H@
                test1.cpp
                @#include "test1.h"

                test1::test1(QWidget *parent, Qt::WFlags flags)
                : QMainWindow(parent, flags)
                {
                centralWidget.resize(600, 300);
                pushButton = new QPushButton(&centralWidget);
                pushButton->setGeometry(QRect(70, 70, 75, 23));
                pushButton->setCheckable(true);
                pushButton->setText("Bold");
                tableWidget = new QTableWidget(&centralWidget);
                tableWidget->setGeometry(QRect(90, 130, 256, 192));
                tableWidget->setRowCount(2);
                tableWidget->setColumnCount(2);
                centralWidget.show();

                connect(pushButton, SIGNAL(clicked()), SLOT(toggleBold()));
                for(int r = 0; r < tableWidget->rowCount(); r++)
                {
                for(int c = 0; c < tableWidget->columnCount(); c++)
                {
                QTableWidgetItem *item = new QTableWidgetItem;
                tableWidget->setItem(r, c, item);
                }
                }
                connect(tableWidget, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(updateButton(int, int, int, int)));

                }

                test1::~test1()
                {

                }

                void test1::toggleBold()
                {
                if(tableWidget->currentColumn() != -1 && tableWidget->currentRow() != -1)
                {
                QTableWidgetItem *item = tableWidget->itemAt(tableWidget->currentRow(), tableWidget->currentColumn());
                QFont font = item->font();
                font.setBold(!font.bold());
                item->setFont(font);
                pushButton->setChecked(item->font().bold());
                }
                }

                void test1::updateButton(int cr, int cc, int pr, int pc)
                {
                if(tableWidget->currentColumn() != -1 && tableWidget->currentRow() != -1)
                {
                QTableWidgetItem *item = tableWidget->itemAt(tableWidget->currentRow(), tableWidget->currentColumn());
                pushButton->setChecked(item->font().bold()) ;
                }
                }@
                Is this the way it should be done? If so, please compile this, run and follow the instruction below:

                Select cell at index (0,0),

                Type something in and press Enter,

                Click the Bold button - the entered text will be bold and button will be checked,

                Select an empty cell - the button should uncheck itself but it doesn't.

                This is what I meant by not working right. Unless I'm doing something wrong.

                Edit: simply moved the code from your previous post to this one; Andre

                "Do not judge, and you will never be mistaken." - Jean-Jacques Rousseau

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  andre
                  wrote on last edited by
                  #8

                  I have compiled your code, and found the issue.

                  Your code to get the current item somehow does not work. It always returns the top left item (0,0). You can spot that if you move to a different cell, and toggle the bold button. You'll notice that the top left cell will change its bold status, not the current cell. Changing your .cpp to this works however:

                  test1.cpp:
                  @#include "test1.h"

                  test1::test1(QWidget *parent, Qt::WFlags flags)
                  : QMainWindow(parent, flags)
                  {
                  centralWidget.resize(600, 300);
                  pushButton = new QPushButton(&centralWidget);
                  pushButton->setGeometry(QRect(70, 70, 75, 23));
                  pushButton->setCheckable(true);
                  pushButton->setText("Bold");
                  tableWidget = new QTableWidget(&centralWidget);
                  tableWidget->setGeometry(QRect(90, 130, 256, 192));
                  tableWidget->setRowCount(2);
                  tableWidget->setColumnCount(2);
                  centralWidget.show();

                  connect(pushButton, SIGNAL(clicked()), SLOT(toggleBold()));
                  for(int r = 0; r < tableWidget->rowCount(); r++)
                  {
                  for(int c = 0; c < tableWidget->columnCount(); c++)
                  {
                  QTableWidgetItem *item = new QTableWidgetItem;
                  tableWidget->setItem(r, c, item);
                  }
                  }
                  connect(tableWidget, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(updateButton(int, int, int, int)));

                  }

                  test1::~test1()
                  {

                  }

                  void test1::toggleBold()
                  {
                  QTableWidgetItem* item = tableWidget->currentItem();
                  if (item) {
                  QFont font = item->font();
                  font.setBold(!font.bold());
                  item->setFont(font);
                  pushButton->setChecked(font.bold());
                  }
                  }

                  void test1::updateButton(int cr, int cc, int pr, int pc)
                  {
                  QTableWidgetItem* item = tableWidget->currentItem();
                  if (item) {
                  pushButton->setChecked(item->font().bold());
                  }
                  }
                  @

                  Notice that instead of going through the row and column numbers, I simply use the currentItem() method directly, and check if it isn't 0. This works just fine in my tests.

                  1 Reply Last reply
                  0
                  • D Offline
                    D Offline
                    d2uriel
                    wrote on last edited by
                    #9

                    Yay. Works... and I've spent like an hour to create all this 2D QFont pointers array and all of it's surrounding (methods for inserting and removing rows and cloumns) as a workaround. Geez...

                    Thank you very much Andre! Let's cut out the useless code of my project then ;-).

                    "Do not judge, and you will never be mistaken." - Jean-Jacques Rousseau

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved