How can you display text with different colors?



  • I am almost done with my GUI applications. So far I can send, read and handle bytes over the serial ports. All my buttons do that they must do and I have a functioning keyboard. There is only one thing which I still need to do and that is displaying the text. At the moment my GUI looks like:
    alt text
    That black thing needs to be my display it is an OpenGlWidget. I used it because it is black and I do not know any better.

    On this display I want to show 40 x 16 characters.. with different colours (20 to be exact).
    There are 5 different displays of which only 1 is shown. The machines which will controll this display can fill the 5 screens with text in the background while displaying one of them. This is not what I have thought of, this is how our machine <> HMI protocol simply is.

    The machine can send instructions like placing the cursor or placing text at the cursor. I already have implemented most of these instructions. I'll show one example of how I can set a lettre:

    if(b > 31 && b < 128 && COMMAND == false) {                                         // if received bytes are > 31 and < 127 AND if the COMMAND flag is false, the byte is treated as a to be printed character
                lettre[index1][column[index1]++][row[index1]] = (char)b;
                                                                                                 // stuffs the character in the text array with the active color.
                qDebug() <<"lettre received";
              }
    

    Principle is simple, I have a 3D array 'lettre' : char lettre[5][40][16]; first index is the screen index, 2nd and 3rd are column and rows respectively. I also have 5x 1D arrays for the columns and letters. So in the code I simply set a lettre on the #index1' screen on column[index1] and row [index1]. And I increase the column[index] by 1. I also have a variable 'index2' and index2 will be used for displaying 1 of the 5 displays.

    But what is the best way to display the text on the screen? I was thinking of using 16 textlabels but I simply do not know the syntax of Qt well enough. I don't know how I can give every letter a different color. I suppose I would also need a 3D array to store color indices in. And I really need a black background for the display. I also need a cursor (colored rectangle) which the machine can turn on and of (setting a bool val in the program)

    In my prescious program processing I simply made 5 display objects each display object would have a 2D array containing 40x16 lettre objects and each lettre object has 2 arguement, character and color index. Ez Pz right? But dat java embedded thing is just too heavy for my Raspberry :(

    So I would like some advice in what widgets to use, how I can implement the colors and I can get me a cursor.

    this is how it looks like in processing
    alt text



  • @bask185 said in How can you display text with different colors?:

    That black thing needs to be my display it is an OpenGlWidget. I used it because it is black and I do not know any better.

    The background colour is not a great way of choosing what widget to use. You can use stylesheets to customise the background colour of any widget

    On this display I want to show 40 x 16 characters

    Looks like a table to me, use QTableView + QStandardItemModel? (ok, yes, you can use QTableWidget but I hate that thing)
    You can set the Qt::ForegroundRole data to chose the text colour and the Qt::BackgroundRole data to implement the cursor (If I understood correctly the "cursor" is just setting the background of a specific letter, correct?)

    Before I can move on writing some code examples I'd need to understand what you mean by "screen" are they 5 things side by side or is it a totally different view?


    Looking at your images it'd look like you did not apply a layout to your widget. You should otherwise you won't be able to allow basic operations as a window resizing. Use spacers to leave gaps and then lay out your widget in a grid (or nested layouts)

    Probably irrelevant:

    I want to show [...] characters [...] char lettre

    character != char. In 2017 we can't be stuck with ASCII.



  • @VRonin said in How can you display text with different colors?:

    Before I can move on writing some code examples I'd need to understand what you mean by "screen" are they 5 things side by side or is it a totally different view?

    a 'screen' is that big black box with 40 x 16 characters you can see on the screen shots. There are 5 of those, but only 1 can be visually displayed at the time due to the available space. The machine can send an instruction which tells the GUI which of the 5 displays is to be shown, therefor I used the variable index2. In processing code is:

    display[index2].paint(); //  0 <= index2 <5
    

    And I indeed have not used any layouts because I am dealing with a fixed resolution, so I did not think I would need the layouts. We simply buy touchmonitors with a 4:3 display ratio and we set our raspberries at 1024 x 768 pixels.

    Probably irrelevant:
    
    I want to show [...] characters [...] char lettre
    character != char. In 2017 we can't be stuck with ASCII.
    

    Yeah, it kinda is ;) The protocol we are working with works with ASCII characters, nothing I can do about it



  • Ok, create 5 QTableWidgets (I'll leave it up to you how you switch from one to the other, QStackedWidget?) and get rid of lettre array.
    declare a private QTableWidgets *monitors[] = {ui->tableWidget1, ui->tableWidget2, ui->tableWidget3, ui->tableWidget4, ui->tableWidget5};

    then in the constructor add:

    for(QTableWidgets* monitor : monitors){
    monitor->setRowCount(40);
    monitor->setColumnCount(16);
    }
    

    now you can use:

    • to set the letter content
    // char b
    monitors[index1]->model()->setData(monitors[index1]->model()->index(column[index1],row[index1]),QChar(b));
    
    • to set the letter colour (here blue)
    monitors[index1]->model()->setData(monitors[index1]->model()->index(column[index1],row[index1]),QBrush(Qt::blue),Qt::ForegroundRole);
    
    • to set the background colour for the letter (here blue):
    monitors[index1]->model()->setData(monitors[index1]->model()->index(column[index1],row[index1]),QBrush(Qt::blue),Qt::BackgroundRole);
    
    • to reset the colours to the default replace QBrush(...) with QVariant()


  • @VRonin said in How can you display text with different colors?:

    declare a private QTableWidgets *monitors[] = {ui->tableWidget1, ui->tableWidget2, ui->tableWidget3, ui->tableWidget4, ui->tableWidget5};

    I am having troubles with this one. I tried both in MainWindow.ccp and in MainWindow.h in the private section looking like this

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include "keyboard.h"
    #include "numpad.h"
    #include <QTableWidget>
    
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private slots:
        void serialReceived();
        void send(QString c);
    
        void on_F1_clicked();
       // many more buttons...
    
    private:
        Ui::MainWindow *ui;
        Keyboard *Kboard;
        Numpad *numpad;
        QTableWidget *monitors[] = {ui->tableWidget1, ui->tableWidget2, ui->tableWidget3, ui->tableWidget4, ui->tableWidget5};
    };
    
    #endif // MAINWINDOW_H
    

    error message:

    C:\Users\sknippels\Documents\GUI\mainwindow.h:64: error: invalid use of incomplete type 'class Ui::MainWindow'
         QTableWidget *monitors[] = {ui->tableWidget1, ui->tableWidget2, ui->tableWidget3, ui->tableWidget4, ui->tableWidget5};
                                       ^
    

    I included the <QTableWidget> library



  • You have to get rid of the OpenGL widget and put the widgets somewhere in Qt Designer. the names I used ui->tableWidget1 are just examples, use the names you set in designer



  • Ok i get it, I only have one small issue left. At first I declared and initialized the array in the constructor. But that gave me the problem that I could not acces it in functions outside the constructor. Than I tried doing it with the rest of the global variables but there it does not reckognize the 'ui' (ui is not declared in this scope). And then I tried declaring the array in the global variables

    #include <QTableWidget>
    
    QSerialPort *serial;        // global variables
    QTableWidget *monitors[5];
    

    and initialize it in the constructor

    monitors[] = {ui->tableWidget_1, ui->tableWidget_2, ui->tableWidget_3, ui->tableWidget_4, ui->tableWidget_5};
    
       for(QTableWidget* monitor : monitors) {
           monitor->setRowCount(16);
           monitor->setColumnCount(40);
       }
    

    But ofcourse :

    C:\Users\sknippels\Documents\GUI\mainwindow.cpp:72: error: expected primary-expression before ']' token
        monitors[] = {ui->tableWidget_1, ui->tableWidget_2, ui->tableWidget_3, ui->tableWidget_4, ui->tableWidget_5};
                 ^
    

    so now I lost it -_-"

    EDIT:

    nvm this fixed it:

     monitors[0] = ui->tableWidget_1;
       monitors[1] = ui->tableWidget_2;
       monitors[2] = ui->tableWidget_3;
       monitors[3] = ui->tableWidget_4;
       monitors[4] = ui->tableWidget_5;
    


  • Do not use global variables unless vital.

    move QTableWidget *monitors[5]; in the private section of the class and add monitors({ui->tableWidget1, ui->tableWidget2, ui->tableWidget3, ui->tableWidget4, ui->tableWidget5}) to the constructor initialisation list



  • alt text The beginning is there.
    Now I just have to figure out

    • how to make the background black
    • remove the grid and everything else I dont need :D

    Thank you once again



  • @bask185 said in How can you display text with different colors?:

    how to make the background black

    in designer, select the table and find Style Sheet in the properties, edit it and put background: black

    remove the grid and everything else I dont need :D

    you can use the loop in the constructor to add:

    for(QTableWidgets* monitor : monitors){
    monitor->setRowCount(40);
    monitor->setColumnCount(16);
    monitor->setShowGrid(false);
    monitor->horizontalHeader()->hide(); // requires #include <QHeaderView>
    monitor->verticalHeader()->hide();
    }
    

    you are free to set column and rows sizes as you prefer and you can use other roles to set other parameters. For example Qt::FontRole to adjust the font family, size and style or the Qt::TextAlignmentRole to decide how the text should align in the cell



  • how can I make the boxes smaller? I found 2 functions which I implemented in the constructor's for-loop but it does not seem to have any effect at all:

    monitor->rowHeight(1); // seems it does not matter what number I fill in
    monitor->columnWidth(1);
    

    0_1490188419292_upload-05292dbf-13bb-44b3-8b3e-94dd907fdf37

    I have read the Qt doc of Qtablewidget 3 times now but I cannot find it. And when I still had the grid I shrank all boxes to absolute mininum size but that was still too lare. I can only fit about 32 characters next to eachother. Is this fixable or should I just use text labels instead?

    EDIT:
    table->horizontalHeader()->setDefaultSectionSize(20);
    table->verticalHeader()->setDefaultSectionSize(20); // Tnx google!



  • table->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    table->horizontalHeader()->resizeSections(20);
    table->verticalHeader()->resizeSections(20);
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.