I'm new to Qt programming and I want to align a QLabel with a custom QGraphicsItem i created. Here's inside my custom item constructor:
QGraphicsProxyWidget* pMyProxy = new QGraphicsProxyWidget(this);
QLabel *label = new QLabel();
label->setText("Some Text");
pMyProxy->setWidget(label);
label->setAlignment(Qt::AlignLeft);
the last line seems to have no effect whether its AlignLeft, Center, or Right.
myItem is a custom rectangle, and I'd like the label to be centered inside the rectangle, as it is the first word of label is being centered at the rectangle instead of the center of the label.
Please help
When you add a widget through a proxy, the proxy is the child of the initial item so its position will be relative to it and by default the position is (0, 0), so you see that although you set an alignment does not change, what you must do to place it in the center through setPos():
#include <QApplication>
#include <QGraphicsProxyWidget>
#include <QGraphicsView>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsView w;
QGraphicsScene *scene = new QGraphicsScene;
QGraphicsRectItem *item = new QGraphicsRectItem;
item->setRect(QRect(0, 0, 200, 200));
item->setBrush(Qt::red);
scene->addItem(item);
QGraphicsProxyWidget *pMyProxy = new QGraphicsProxyWidget(item);
QLabel *label = new QLabel();
label->setText("Some Text");
pMyProxy->setWidget(label);
pMyProxy->setPos(item->boundingRect().center()-label->rect().center());
w.setScene(scene);
w.show();
return a.exec();
}
Assuming this is the item, you should do the following:
QGraphicsProxyWidget *pMyProxy = new QGraphicsProxyWidget(this);
QLabel *label = new QLabel();
label->setText("Some Text");
pMyProxy->setWidget(label);
pMyProxy->setPos(boundingRect().center()-label->rect().center());
If you want to access the widget regarding the item you must follow the children tree:
QGraphiscScene
└── QGraphiscItem
└── (children)
QGraphicsProxyWidget
└── (widget)
QLabel
Example:
main.cpp
#include <QApplication>
#include <QGraphicsProxyWidget>
#include <QGraphicsView>
#include <QLabel>
#include <QTimer>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsView w;
QGraphicsScene *scene = new QGraphicsScene;
QGraphicsRectItem *item = new QGraphicsRectItem;
item->setRect(QRect(0, 0, 200, 200));
item->setBrush(Qt::red);
scene->addItem(item);
item->setFlag(QGraphicsItem::ItemIsSelectable, true);
item->setFlag(QGraphicsItem::ItemIsMovable, true);
QGraphicsProxyWidget *pMyProxy = new QGraphicsProxyWidget(item);
QLabel *label = new QLabel();
label->setText("Some Text");
pMyProxy->setWidget(label);
pMyProxy->setPos(item->boundingRect().center()-label->rect().center());
w.setScene(scene);
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&](){
if(!scene->selectedItems().isEmpty()){
auto *item = scene->selectedItems().first();
if(!item->childItems().isEmpty()){
auto proxy = static_cast<QGraphicsProxyWidget *>(item->childItems().first());
if(proxy){
auto label = qobject_cast<QLabel *>(proxy->widget());
if(label){
label->setText(QString("x: %1, y: %2").arg(item->pos().x()).arg(item->pos().y()));
}
}
}
}
});
timer.start(100);
w.show();
return a.exec();
}
Related
On GraphicsView(QGraphicsView) i set scene(QGraphicsScene), i am adding qdial object throgh qgraphicsproxy widget, place sizegrip on bottom right position?
`
QDial *dial = new QDial(); // dial object
plot->setGeometry(event->pos().x(),event->pos().y(),80,80);
QSizeGrip * sizeGrip = new QSizeGrip(dial );// placing sizegrip
QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget();
proxy->setWidget(dial );
proxy->setFlag(QGraphicsItem::ItemIsMovable,true);
scene->addItem(proxy);`
image of output
You have to use a layout as I show below:
#include <QApplication>
#include <QDial>
#include <QGraphicsProxyWidget>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QSizeGrip>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsView view;
QGraphicsScene *scene = new QGraphicsScene(&view);
view.setScene(scene);
QDial *dial = new QDial;
QSizeGrip * sizeGrip = new QSizeGrip(dial);
QHBoxLayout *layout = new QHBoxLayout(dial);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(sizeGrip, 0, Qt::AlignRight | Qt::AlignBottom);
QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget();
proxy->setWidget(dial);
proxy->setFlag(QGraphicsItem::ItemIsMovable,true);
scene->addItem(proxy);
view.show();
return a.exec();
}
everyone! I try to set a click property to a QMediaPlayer Element, but I can not find the mode to make it, and if I try to put a button in front to Video, the button puts behind to video, even with
button->raise();
videoWidget->lower();
And If I put a Button to fullscreen the screen turns in black and don't shows the video
this id the code of the video player
QMediaPlayer *player = new QMediaPlayer(this);
QVideoWidget *vw = new QVideoWidget(this);
QMediaPlaylist *PlayList = new QMediaPlaylist(this);
PlayList->addMedia(QUrl::fromLocalFile("/home/user/Videos/video.mp4"));
PlayList->setPlaybackMode(QMediaPlaylist::Loop);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(vw);
player->setVideoOutput(vw);
player->setPlaylist(PlayList);
vw->setGeometry(0,0,800,480);
vw->show();
player->play();
One possible solution is to create a widget where the QVideoWidget is placed through a layout, the button is also added and we change the position through the resizeEvent() event.
#include <QApplication>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QPushButton>
#include <QUrl>
#include <QVBoxLayout>
#include <QVideoWidget>
#include <QDebug>
class VideoWidgetButton: public QWidget{
QPushButton *btn;
QVideoWidget *vw;
QMediaPlayer *player;
public:
VideoWidgetButton(QWidget *parent=Q_NULLPTR):QWidget(parent){
setLayout(new QVBoxLayout);
layout()->setContentsMargins(0, 0, 0, 0);
vw = new QVideoWidget(this);
btn = new QPushButton(this);
btn->setIcon(QIcon(":/icons/tux.jpeg"));
btn->resize(QSize(128, 128));
btn->setIconSize(QSize(128, 128));
connect(btn, &QPushButton::clicked, [](){
qDebug()<<"clicked";
});
layout()->addWidget(vw);
player = new QMediaPlayer(this);
player->setVideoOutput(vw);
QMediaPlaylist *playList = new QMediaPlaylist(this);
playList->addMedia(QUrl("qrc:/video/SampleVideo_1280x720_1mb.mp4"));
playList->setPlaybackMode(QMediaPlaylist::Loop);
player->setPlaylist(playList);
player->play();
}
protected:
void resizeEvent(QResizeEvent *ev){
btn->move(rect().bottomRight()-btn->rect().bottomRight());
return QWidget::resizeEvent(ev);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
VideoWidgetButton w;
w.resize(640, 480);
w.show();
return a.exec();
}
The complete example can be found in the following link.
I have a custom widget with some standard child widgets inside. If I make a separate test project and redefine my custom widget to inherit QMainWindow, everything is fine. However, if my custom widget inherits QWidget, the window opens, but there are no child widgets inside.
This is the code:
controls.h:
#include <QtGui>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
class Controls : public QWidget
{
Q_OBJECT
public:
Controls();
private slots:
void render();
private:
QWidget *frame;
QWidget *renderFrame;
QVBoxLayout *layout;
QLineEdit *rayleigh;
QLineEdit *mie;
QLineEdit *angle;
QPushButton *renderButton;
};
controls.cpp:
#include "controls.h"
Controls::Controls()
{
frame = new QWidget;
layout = new QVBoxLayout(frame);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
frame->setLayout(layout);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
main.cpp:
#include <QApplication>
#include "controls.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Controls *controls = new Controls();
controls->show();
return app.exec();
}
This opens up a window with correct dimensions, but with no content inside.
Bear in mind this is my first day using Qt. I need to make this work without inheriting QMainWindow because later on I need to put this on a QMainWindow.
You're missing a top level layout:
Controls::Controls()
{
... (yoour code)
QVBoxLayout* topLevel = new QVBoxLayout(this);
topLevel->addWidget( frame );
}
Or, if frame is not used anywhere else, directly:
Controls::Controls()
{
layout = new QVBoxLayout(this);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
Note that setLayout is done automatically when QLayout is created (using parent widget)
You'll want to set a layout on your Controls class for managing its child sizes. I'd recommend removing your frame widget.
controls.cpp
Controls::Controls()
{
layout = new QVBoxLayout(this);
.
.
.
}
main.cpp
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
I'm building a simple application, the main window have to shows two widgets (QTreeView on the right, QTabWidget on the left), to perform this i use a QHBoxLayout.
This is the code i've written(constructor of MainWindow):
MainWindow::MainWindow()
{
mainLayout = new QHBoxLayout(this);
tabber = new QTabWidget(this);
analysisTreeView = new QTreeView(this);
tabber->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainLayout->addWidget(tabber, 0);
mainLayout->addWidget(analysisTreeView, 0);
createActions();
createMenus();
createToolBars();
connect(tabber, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
setLayout(mainLayout);
}
But when i run the application the main window shows no widgets. Why?
On request, i add some code:
Once a button in the mainwindows's toolbar is clicked a new tab is added to tabber:
void MainWindow::newSheet()
{
GraphicsScene *newScene = new GraphicsScene(itemMenu,this);
QGraphicsView *newView = new QGraphicsView(this);
newScene->setSceneRect(-200, -200, 400, 400);
newView->scale(1.5,1.5);
newView->setCacheMode(QGraphicsView::CacheBackground);
newView->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
newView->setRenderHint(QPainter::Antialiasing);
newView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
newView->setScene(newScene);
sheetList.append(newView);
tabber->addTab(newView,"PNC");
connect(newScene, SIGNAL(itemInserted(PItem*)), this, SLOT(itemInserted(PItem*)));
connect(newScene, SIGNAL(requestUpdateGUI(GraphicsScene*)), this, SLOT(updateGUI(GraphicsScene*)));
}
My main.cpp:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);
QApplication a(argc, argv);
MainWindow window;
window.showMaximized();
return a.exec();
}
I suppose your class specializes QMainWindow. If so, it needs a centralWidget to be set:
MainWindow::MainWindow()
{
// added by jpo38
QWidget* mainWidget = new QWidget( this );
setCentralWidget( mainWidget );
// end added by jpo38
mainLayout = new QHBoxLayout(mainWidget);
tabber = new QTabWidget(mainWidget);
analysisTreeView = new QTreeView(mainWidget);
tabber->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainLayout->addWidget(tabber, 0);
mainLayout->addWidget(analysisTreeView, 0);
createActions();
createMenus();
createToolBars();
connect(tabber, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
setLayout(mainLayout);
}
I have a QWidget which contains a QVBoxLayout and that layout contains a QLabel and QToolButtons. My problem is, that the QLabel takes all the space. The only solution I found is to set maximumHeight to the QLabel, but if I do that, the Qt::AlignTop doesn't work anymore.
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget window_main;
QWidget *widget_steps = new QWidget(&window_main);
widget_steps->setFixedWidth(75);
widget_steps->move(QPoint(0, 0));
widget_steps->setStyleSheet("background-color: red;");
QVBoxLayout *layout_steps = new QVBoxLayout(widget_steps);
layout_steps->setContentsMargins(0, 0, 0, 0);
layout_steps->setSpacing(0);
QLabel *label_steps_start = new QLabel("steps:");
label_steps_start->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
label_steps_start->setStyleSheet("background-color: blue;");
layout_steps->addWidget(label_steps_start);
QToolButton *tbutton_step1 = new QToolButton();
layout_steps->addWidget(tbutton_step1);
QToolButton *tbutton_step2 = new QToolButton();
layout_steps->addWidget(tbutton_step2);
QToolButton *tbutton_step3 = new QToolButton();
layout_steps->addWidget(tbutton_step3);
window_main.showMaximized();
return a.exec();
}
Here a picture that shows how much space the QLable takes(the blue space):
So please help to minimize the space the QLable takes :)
Your problem is that the tool buttons have a fixed size, and therefore when resizing, the label is the only type that can grow: Therefore:
After adding the label, add stretch to the layout:
layout_steps->addWidget(label_steps_start);
layout_steps->addStretch();
Modified code - adds stretch at the bottom. Label size remains fixed, and buttons remain under it. I've removed the whole main window around the outside for the sake of testing.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *widget_steps = new QWidget;
widget_steps->setFixedWidth(75);
widget_steps->move(QPoint(0, 0));
widget_steps->setStyleSheet("background-color: red;");
QVBoxLayout *layout_steps = new QVBoxLayout(widget_steps);
layout_steps->setContentsMargins(0, 0, 0, 0);
layout_steps->setSpacing(0);
QLabel *label_steps_start = new QLabel("steps:");
label_steps_start->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
label_steps_start->setStyleSheet("background-color: blue;");
layout_steps->addWidget(label_steps_start);
//--- Removed.... layout_steps->addStretch();
QToolButton *tbutton_step1 = new QToolButton();
layout_steps->addWidget(tbutton_step1);
QToolButton *tbutton_step2 = new QToolButton();
layout_steps->addWidget(tbutton_step2);
QToolButton *tbutton_step3 = new QToolButton();
layout_steps->addWidget(tbutton_step3);
layout_steps->addStretch(); //<----- Added!
widget_steps->show();
return a.exec();
}
One way you could do is to set the stretch factor for that particular widget inside the QVBoxLayout. You can find the documentation for that in here.
Basically, when you add a widget you can set that, for instance:
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QToolButton>
#include <QtWidgets/QVBoxLayout>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget window_main;
QWidget *widget_steps = new QWidget(&window_main);
widget_steps->setFixedWidth(75);
widget_steps->move(QPoint(0, 0));
widget_steps->setStyleSheet("background-color: red;");
QVBoxLayout *layout_steps = new QVBoxLayout(widget_steps);
layout_steps->setContentsMargins(0, 0, 0, 0);
layout_steps->setSpacing(0);
QLabel *label_steps_start = new QLabel("steps:");
label_steps_start->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
label_steps_start->setStyleSheet("background-color: blue;");
layout_steps->addWidget(label_steps_start, 3, Qt::AlignTop);
layout_steps->addStretch();
QToolButton *tbutton_step1 = new QToolButton();
layout_steps->addWidget(tbutton_step1, 1);
QToolButton *tbutton_step2 = new QToolButton();
layout_steps->addWidget(tbutton_step2, 1);
QToolButton *tbutton_step3 = new QToolButton();
layout_steps->addWidget(tbutton_step3, 1);
window_main.showMaximized();
return a.exec();
}