How can you display text with different colors?
-
wrote on 22 Mar 2017, 08:42 last edited by
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:
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.
-
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:
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
wrote on 22 Mar 2017, 08:57 last edited by VRonin@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 theQt::ForegroundRole
data to chose the text colour and theQt::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.
-
@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 theQt::ForegroundRole
data to chose the text colour and theQt::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.
wrote on 22 Mar 2017, 09:22 last edited by@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
-
wrote on 22 Mar 2017, 10:12 last edited by VRonin
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 privateQTableWidgets *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(...)
withQVariant()
-
@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
wrote on 22 Mar 2017, 10:48 last edited by@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
-
wrote on 22 Mar 2017, 10:56 last edited by
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 -
wrote on 22 Mar 2017, 11:18 last edited by bask185
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;
-
wrote on 22 Mar 2017, 11:23 last edited by
Do not use global variables unless vital.
move
QTableWidget *monitors[5];
in the private section of the class and addmonitors({ui->tableWidget1, ui->tableWidget2, ui->tableWidget3, ui->tableWidget4, ui->tableWidget5})
to the constructor initialisation list -
wrote on 22 Mar 2017, 11:32 last edited by
-
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
wrote on 22 Mar 2017, 11:42 last edited by VRonin@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 theQt::TextAlignmentRole
to decide how the text should align in the cell -
wrote on 22 Mar 2017, 13:17 last edited by bask185
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);
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! -
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);
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!wrote on 22 Mar 2017, 14:17 last edited bytable->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); table->horizontalHeader()->resizeSections(20); table->verticalHeader()->resizeSections(20);
1/12