I have Qt C++ related question.
I need window divided in 4 parts. In 3 of them should be QTableWidgets (red, yellow and green areas on the example picture), but they must be synchronized in pairs (red and yellow, red and green - the lines of one continue the lines of the other) so when you scroll red QTableWidget horizontally - it at the same time scrolls horizontally green QTableWidget (and vice versa), and you scroll red QTableWidget vertically - it at the same time scrolls vertically yellow QTableWidget (and vice versa).
Additionally I need to have a possibility to adjust area sizes dragging borders (grey arrows on the picture). So when I drag each border - it changes size of 2 corresponding QTableWidgets.
I would be glad to any idea of how to realize that. Thank in advance!
example
Minimal example to reproduce your image:
#include <QApplication>
#include <QTableWidget>
#include <QSplitter>
#include <QHBoxLayout>
#include <QScrollBar>
#include <QHeaderView>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//////////////////////////////////////////////////////////////////////////
/// Things you can do in Qt Designer
QWidget mainW;
QSplitter *hSplitter = new QSplitter(Qt::Horizontal,&mainW);
QSplitter *vSplitter1 = new QSplitter(Qt::Vertical,&mainW);
QSplitter *vSplitter2 = new QSplitter(Qt::Vertical,&mainW);
QTableWidget *tableRed = new QTableWidget(6,6,&mainW);
tableRed->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableRed->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableRed->verticalHeader()->hide();
tableRed->horizontalHeader()->hide();
QTableWidget *tableGreen = new QTableWidget(1,6,&mainW);
tableGreen->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableGreen->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableGreen->verticalHeader()->hide();
tableGreen->horizontalHeader()->hide();
QTableWidget *tableYellow = new QTableWidget(6,2,&mainW);
tableYellow->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableYellow->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableYellow->verticalHeader()->hide();
tableYellow->horizontalHeader()->hide();
QWidget *topLeft = new QWidget(&mainW);
vSplitter1->addWidget(topLeft);
vSplitter1->addWidget(tableYellow);
vSplitter2->addWidget(tableGreen);
vSplitter2->addWidget(tableRed);
hSplitter->addWidget(vSplitter1);
hSplitter->addWidget(vSplitter2);
QHBoxLayout *mainLay = new QHBoxLayout(&mainW);
mainLay->addWidget(hSplitter);
//////////////////////////////////////////////////////////////////////////
QTimer::singleShot(0,vSplitter1,[vSplitter2,vSplitter1](){vSplitter1->setSizes(vSplitter2->sizes());});
QObject::connect(vSplitter1,&QSplitter::splitterMoved,vSplitter2,[vSplitter2,vSplitter1](){vSplitter2->setSizes(vSplitter1->sizes());});
QObject::connect(vSplitter2,&QSplitter::splitterMoved,vSplitter1,[vSplitter2,vSplitter1](){vSplitter1->setSizes(vSplitter2->sizes());});
QObject::connect(tableRed->verticalScrollBar(),&QScrollBar::valueChanged,tableYellow->verticalScrollBar(),&QScrollBar::setValue);
QObject::connect(tableYellow->verticalScrollBar(),&QScrollBar::valueChanged,tableRed->verticalScrollBar(),&QScrollBar::setValue);
QObject::connect(tableRed->horizontalScrollBar(),&QScrollBar::valueChanged,tableGreen->horizontalScrollBar(),&QScrollBar::setValue);
QObject::connect(tableGreen->horizontalScrollBar(),&QScrollBar::valueChanged,tableRed->horizontalScrollBar(),&QScrollBar::setValue);
mainW.show();
return a.exec();
}
Related
I am using the qtcharts module of qt.
I am using c++ but it does not matter if the solution comes for another language (I will translate it afterwards).
Problem: I plot a bunch of QLineSeries in a QChart and I want to display the point labels only when hovering them.
I planned to use the signal QXYSeries::hovered() to detect when the mouse moves over a point (the same when the mouse moves away the point).
I know that there exists a member function QXYSeries::setPointLabelsVisible() but it makes visible all the points of the series.
I want to be able to display only one point at a time because the series are relatively large and displaying all the labels would degrade the readability.
Question: Is it possible to display only one point label for a QLineSeries ? If yes, how ?
I could not find such a feature anywhere in the Qt documentation.
Here is a baseline code sample to start with (for convenience):
Declaration:
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
};
Definition:
#include <QApplication>
#include <QLineSeries>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QChartView>
#include <QDateTime>
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
MainWindow::MainWindow()
{
setWindowTitle("QtCharts baseline");
resize(800, 500);
QtCharts::QChart * chart = new QtCharts::QChart;
chart->setTitle("Baseline sample");
chart->legend()->setAlignment(Qt::AlignRight);
QtCharts::QDateTimeAxis * time_axis = new QtCharts::QDateTimeAxis;
time_axis->setFormat("hh:mm:ss");
time_axis->setTitleText("Time");
time_axis->setTickCount(5);
QtCharts::QValueAxis * value_axis = new QtCharts::QValueAxis;
value_axis->setTitleText("Value (unit)");
value_axis->setTickCount(6);
chart->addAxis(time_axis, Qt::AlignBottom);
chart->addAxis(value_axis, Qt::AlignLeft);
QtCharts::QLineSeries * ls = new QtCharts::QLineSeries;
ls->setName("Test series");
ls->setPointsVisible(true);
//ls->setPointLabelsVisible(true);
QDateTime dt = QDateTime::currentDateTime();
ls->append(dt.toMSecsSinceEpoch(), -10);
ls->append(dt.addSecs(1).toMSecsSinceEpoch(), 8);
ls->append(dt.addSecs(2).toMSecsSinceEpoch(), 27);
ls->append(dt.addSecs(3).toMSecsSinceEpoch(), 12);
ls->append(dt.addSecs(4).toMSecsSinceEpoch(), 42);
chart->addSeries(ls);
ls->attachAxis(time_axis);
ls->attachAxis(value_axis);
QtCharts::QChartView * view = new QtCharts::QChartView;
view->setChart(chart);
this->setCentralWidget(view);
}
One technique you could try is making a "shadow" copy of the line series with just the one or few points you need, sitting on top of the actual data line. Draw with a transparent pen so the line doesn't show up but set the labels to be visible. You can add/remove/change points to the shadow copy of the line series, and only the labels you want drawn can be added to the series. The link shows one
example of the technique.
From this source code:
#include "mainwindow.h"
#include <Q3DScatter>
using namespace QtDataVisualization;
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
Q3DScatter *graph = new Q3DScatter;
QWidget *widget = QWidget::createWindowContainer(graph);
setCentralWidget(widget);
}
MainWindow::~MainWindow() {}
I get:
See that wall directly in front, its grayed (can I describe it this way?) if compared to the other walls. How can I tweak grid lines that way? I mean just one wall.
Basically, you can change the color of the grid-line with the following code.
#include <QApplication>
#include <QtDataVisualization/Q3DScatter>
#include <QtDataVisualization/Q3DLight>
#include <QtDataVisualization/Q3DTheme>
#include <QDebug>
#include <QTimer>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
auto scatter = new QtDataVisualization::Q3DScatter;
auto widget=QWidget::createWindowContainer(scatter);
widget->show();
scatter->activeTheme()->setType(QtDataVisualization::Q3DTheme::ThemeQt);
scatter->activeTheme()->setGridLineColor(QColor("red"));
auto light = scatter->scene()->activeLight();
auto camera = scatter->scene()->activeCamera();
int counter = 0;
QTimer timer;
timer.start(1 / 60);
QObject::connect(&timer, &QTimer::timeout, [&]() {
camera->setXRotation(counter++/60);
});
return a.exec();
}
Still, there seems to be no effect on how the grid-lines are rendered. I think this is do to the lighting of the 3D scene and of course of the camera position.
My small example program rotates the camera of the scene and therefore also the lighting of the grid-lines changes.
I think, there is little you can do here, as the interfaces doesn't allow you to change the shader code of the grid-lines.
Solution might be to add a custom 3d item, set a mesh and texture color. Resize the item to look like a grid axis and set the position. Repeat the idea for as many axis lines it is required.
Wondering if there is a (better) alternative approach.
Im working with QT and I have a form with a QLabel in a QFrame. I want to set the QLabel's geometry so the bottom part of the QLabel is in the same place of the bottom of the frame. Since the label is longer than the frame, it's y coordinate should be negative.
int pos = ui->imageFrame->height() - ui->imageLabel->pixmap()->height();
ui->imageLabel->setGeometry(0, pos, ui->imageFrame->width(), p.height());
Although when printing the QLabel's geometry, the y coordinate is correct, the label is showing on the upper part of the frame.
Help is much appreciated.
You can set the label's alignment with setAlignment. Here's a working example:
#include <QtWidgets>
#include "MyWidget.h"
MyWidget::MyWidget()
{
setFixedSize(200,200);
QLabel *label = new QLabel;
label->setPixmap(QPixmap("/some/image/file.jpg"));
label->setAlignment(Qt::AlignBottom);
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(label);
hbox->setContentsMargins(0,0,0,0);
setLayout(hbox);
}
I am working on a video processing project. For debugging I need to append ROI of some frames in to QLabel of specified width. I need to append the subframes to the label....Got any ideas for doing that??
You Can Use QLayout(horizintal, Vertical e t.c) and QLabel. Try to dynamically Create QLabels as needed, and the add to the Layout. with this, U can add as Much pictures as you want... Hope it helps.
#include <QtGui/QApplication>
#include <QLabel>
#include <QImage>
#include <QLayout>
#include <QMainWindow>
#include <QStringList>
#include <QDebug>
#include <QScrollArea>
//This assumes that the pictures are in the application's Current working directory
//Four pictures used with names 1.png,2.png,3.png and 4.png respectively
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
QWidget *central = new QWidget(&w);
w.setCentralWidget(central);
QLayout *test_layout = new QVBoxLayout(central);
QStringList file_names;
file_names <<"1"<<"2"<<"3"<<"4";
foreach(QString pics, file_names){
QLabel* imagethings = new QLabel();
QImage image(QString("%1.png").arg(pics));//QImage's Constructor takes a file path
imagethings->setPixmap(QPixmap::fromImage(image));
test_layout->addWidget(imagethings);//append the new image
}
// remove Space as a result of widget Margin(see link for Box Model below)
central->setStyleSheet("QLabel{border:0px; margin:0px; padding:0px;}");
central->layout()->setContentsMargins(0,0,0,0);//remove Spac as a result of Layout Margins
//Please try to take advantage of Qt's Detailed Documentatio that Comes with the SDK
w.show();
return a.exec();
}
http://doc.qt.digia.com/qt/stylesheet-customizing.html -Box Model
http://doc.qt.digia.com/qt/stylesheet-reference.html -Stylesheet Reference
You can Check through the Links for the Stylesheet to discern better
I have written a program that uses widgets as container (for other widgets). Because the contents of the container varies along the program life, the container widget has a layout associated to it so it resizes properly.
The problem is that the container seems to consume some space.
In the following program, I have reproduced the problem: I have a group with a few labels, where one of them is included in a container (the widget w -and its layout t- includes the label "what is that extra space?").
My goal is to get the spacing between all labels the same, regardless whether they are in containers or not. (the container should not consume space)
I have also tried to color the different parts of the widgets. Where is my padding? What is the extra space between the widgets (between the blue). And how do I remove it?
#include <QApplication>
#include <QtCore>
#include <QMainWindow>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <stdlib.h>
QMdiArea* g1;
QGroupBox* g1a;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow* main_window = new(QMainWindow);
main_window->resize(200, 200);
main_window->setWindowTitle("Hello");
g1a = new QGroupBox("G1A", g1);
QVBoxLayout *g1a_l = new QVBoxLayout(g1a);
g1a_l->setSpacing(0);
main_window->setCentralWidget(g1a);
g1a_l->addWidget((QLabel*)new QLabel(" Nice Label1"));
g1a_l->addWidget((QLabel*)new QLabel(" Nice Label2"));
QWidget* w=new QWidget(0);
w->setStyleSheet( "border: 2 solid blue; padding: 2 solid yellow;" );
QVBoxLayout* t=new QVBoxLayout(w);
t->setSpacing(0);
t->addWidget(new QLabel("What is that extra space??",w));
g1a_l->addWidget(w);
g1a_l->addWidget((QLabel*)new QLabel(" Nice Label3"));
g1a_l->addWidget((QLabel*)new QLabel(" Nice Label4"));
//sub_window->adjustSize();
main_window->show(); //How to I get that to recaclulate the size of its contents?
return app.exec();
}
This is contentsMargin
To remove it:
t->setContentsMargins(0,0,0,0);
The space you referring to is a content margin. The docu here describes how the widgets are drawn. To get rid of that extra space you have to call:
widget->setContentsMargins(0, 0, 0, 0);
I believe the end result should look like this:
The method I recall to control spacing is to add dedicated QSpacerItem items between the widgets.
But I'm first trying to figure out what w is doing. Why not call g1a_l->addLayout(t); directly?