I'm new to QT. I used following code to add a button in to a QGraphicScene
QGraphicsScene* scene = new QGraphicsScene;
QPushButton *btnuser = new QPushButton();
btnuser->resize(32, 32);
btnuser->setGeometry(QRect(QPoint(50, 50),QSize(32, 32)));
btnuser->setText("1");
btnuser->setAccessibleName("1");
connect(btnuser, SIGNAL( clicked() ), this, SLOT( on_btnProcess_clicked() ) );
scene->addWidget(btnuser);
But in the output there is a rectangle behind the button. How can I remove that?
I solved this problem by setting minimum width and height.
QPushButton *btnuser = new QPushButton();
btnuser->setMinimumHeight(20);
btnuser->setMinimumWidth(20);
Then I set the same width and height for the button in setGeometry method
btnuser->setGeometry(QRect(QPoint(pointx,pointy),QSize(20, 20)));
Related
I have made a custom Window in Qt and now facing to resizing problem.
I want a free space around my QWidget (Qt::FramelessWindowHint) so i can process the Mouse Hover+Leave+press+release events in that area and in this events i change the cursor shape and resizing the widget.
(I don't want mouseEvent for widget but for that space)
How could i get such area ?
I suppose your QWidget is added to a QLayout at some point. Then just ask the containing QLayout to reserve some free space around it's content by calling [setContentsMargins].
Example, you had:
QWidget* widget = new QWidget( parent );
parent->layout()->addWidget( widget );
Then, just add:
parent->layout()->setContentsMargins( 100,100,100,100 );
This will guarantee that widget has 100 pixels of empty area around it.
To be more generic, and it case you had no parent, you can create an intermediate QWidget like that:
You had:
QWidget* myWidget = new QWidget( NULL );
widget->show();
Just do:
QWidget* parentWithEmptySpaceBorder = new QWidget( NULL );
parentWithEmptySpaceBorder->setLayout( new QVBoxLayout() );
parentWithEmptySpaceBorder->layout()->setContentsMargins( 100,100,100,100 );
QWidget* myWidget = new QWidget( NULL );
parentWithEmptySpaceBorder->layout()->addWidget( myWidget );
parentWithEmptySpaceBorder->show();
I have this test case:
// Scroll
QScrollArea *sa = new QScrollArea(ui->centralWidget);
sa->setWidgetResizable( true );
// Layout for widgets
QVBoxLayout *vl_2 = new QVBoxLayout();
vl_2->setSpacing(0);
// Widget to attach the scroll to and the layout
QWidget *widget = new QWidget()
widget->setLayout(vl_2);
sa->setWidget(widget);
// Test widgets
QComboBox *cb_1 = new QComboBox();
QComboBox *cb_2 = new QComboBox();
vl_2->addWidget( cb_1 );
vl_2->addWidget( cb_2 );
And the widgets have 0 space between them.
But if I add them to a QTabWdiget, it all breaks as if QTabWidget does not respect the set setSpacing(0);.
// TabWidget
QTabWidget *run_results = new QTabWidget(ui->centralWidget);
run_results->resize( this->size().width() -20, this->size().height() -80 );
run_results->show();
// Scroll
QScrollArea *sa = new QScrollArea(ui->centralWidget);
sa->setWidgetResizable( true );
// Layout for widgets
QVBoxLayout *vl_2 = new QVBoxLayout();
vl_2->setSpacing(0);
// Widget to attach the scroll to and the layout
QWidget *widget = new QWidget()
widget->setLayout(vl_2);
sa->setWidget(widget);
// Add the scroll to as the TabWidget tab.
run_results->addTab(sa, "test");
// Test widgets
QComboBox *cb_1 = new QComboBox();
QComboBox *cb_2 = new QComboBox();
vl_2->addWidget( cb_1 );
vl_2->addWidget( cb_2 );
Anyone know what I need to do to force QTabWidget to not resize and move my widgets so that they take all the space?
I tried to add Qt::AlignTop to the addWdiget but it did nothing other than place the first widget at the top and the next in the middle of the screen.
I understand where I went wrong.
In the first case I add my scrollarea as a sub-widget to the centralwidget. In the second example I add the scrollarea as the centralwidget which expands it to the whole tabwidget.
I resolved the second case by first adding a holder QWidget as the tabwidget and then adding the scrollarea as a sub-widget to it.
I am displaying QToolButtons with icon plus text (Qt::ToolButtonTextBesideIcon) outside of a tool bar. Each button has a QAction associated with it which determines the used icon and the displayed text. All those buttons are placed inside a QGridLayout. So far so good.
Unfortunately, it looks like that as soon as you add a QAction to a QToolButton, Qt automatically decides to shrink it down to the minimal size, which is not what I want given my QGridLayout. I used the following lines to correct that behavior in the horizontal dimension:
QToolButton* pButton = new QToolButton(0);
pButton->addDefaultAction(pAction);
pButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
pButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
However that still leaves my button with a smaller height than a regular (push) button. I already tried various other size policies without success.
How to best solve this issue? Is there a reliable way to determine the "normal" button height?
One idea I had was to create a regular dummy button, place it in the same layout and then read its size. This size could then be applied to my QToolButton and the dummy button would be destroyed again. Is there a more elegant / reliable way?
I do not understand what do you want to achieve.
Difference between QPushButton and QToolButton is that, QToolButton has implemented PopupMenu ( can be done easily for QPushButton also )
As I understand visual difference is only small arrow in lower right corner of QToolButton, when you use added QActions to QToolButton
This arrow is for me only difference between QToolButton and QPushButton. But maybe I am missing something.
From your examples ( QToolButton with icon + text: How to center both? )
it does not look like you want to use that popup feature. Thats why I do not understand, why to use QToolButton instead of QPushButtons.
In this example shows:
1) Same height of QToolButton and QPushButton
2) PopuMenu for QPushButton
As for me, I do not understand why to use QToolButton and try to make it look like QPushButton when it is simple to use QPushButton as QToolButton
#include <QtGui>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Prepare layout
QMainWindow *window = new QMainWindow;
QWidget *centralWidget = new QWidget(window);
QGridLayout *grid = new QGridLayout(centralWidget);
QTextEdit *textEdit = new QTextEdit();
window->setCentralWidget(centralWidget);
QAction *toolAction = new QAction(window->style()->standardIcon(QStyle::SP_MediaPlay), "ToolButton", window);
QObject::connect(toolAction, &QAction::triggered, [=]() {
qDebug() << "action";
});
QPushButton *pushButton = new QPushButton(toolAction->icon(), "PushButton1", window);
pushButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QPushButton *pushButton2 = new QPushButton(toolAction->icon(), "PushButton2", window);
pushButton2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QPushButton *pushButton3 = new QPushButton(toolAction->icon(), "PushButton2", window);
pushButton3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QObject::connect(pushButton3, &QPushButton::released, [window, pushButton3, toolAction](){
QMenu menu;
menu.addAction(toolAction);
QPoint pos = window->mapToGlobal(pushButton3->pos());
pos += QPoint(0, pushButton3->height());
menu.exec(pos);
});
QObject::connect(pushButton, SIGNAL(pressed()), toolAction, SLOT(trigger()));
QObject::connect(pushButton2, SIGNAL(pressed()), toolAction, SLOT(trigger()));
QToolButton *toolButton = new QToolButton(window);
toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolButton->setText("Popup action");
toolButton->addAction(toolAction);
toolButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QToolButton *toolButton2 = new QToolButton(window);
toolButton2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolButton2->setDefaultAction(toolAction);
toolButton2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
toolButton->setMaximumHeight(pushButton->sizeHint().height());
toolButton->setMinimumHeight(pushButton->sizeHint().height());
toolButton2->setMaximumHeight(pushButton->sizeHint().height());
toolButton2->setMinimumHeight(pushButton->sizeHint().height());
grid->addWidget(textEdit ,0,0,1,2);
grid->addWidget(toolButton ,1,0,1,1);
grid->addWidget(pushButton ,1,1,1,1);
grid->addWidget(toolButton2 ,2,0,1,1);
grid->addWidget(pushButton2 ,2,1,1,1);
grid->addWidget(pushButton3 ,3,0,1,2);
window->show();
return a.exec();
}
I wanna do this: When I enlarge my mainwindow pressing and moving mouse, I want the widget(like a button) to move accordingly(not resize the button) to make sure the button is always at the edge of my mainwindow. I can do it in this way:
void MainWindow::resizeEvent(QResizeEvent *e)
{
int x,y,newx,newy,resizex,resizey;
newx = this->width();
newy = this->height();
resizex = newx - mainwindowWidth;
resizey = newy - mainwindowHeight;
x = ui->button->pos().x();
y = ui->button->pos().y();
ui->button->move(x+resizex, y+resizey);
mainwindowWidth = newx;
mainwindowHeight = newy;
}
But it's so complex. Does QPushButton have any attribute to do this job easily? Waiting for your answer. Any advice would be helpful. Thanks in advance.
You can add your pushbutton to a layout and add spacers to push the button to the edge.
Heres an example:
QHBoxLayout *hlayout = new QHBoxLayout;
ui->verticalLayout->addLayout(hlayout);
QPushButton *button = new QPushButton("Button");
hlayout->addWidget(button);
QSpacerItem *item = new QSpacerItem(1,1, QSizePolicy::Expanding, QSizePolicy::Fixed);
hlayout->addSpacerItem(item);
QScrollArea, for some reason, is ignoring the contentMargins setting when I set QGraphicsView as its widget. Looking at the snippet below, can someone please tell if I'm doing something wrong or it could be a bug in the SDK?
Snippet 1 (works perfect):
QWidget *appWindow = new QWidget;
QScrollArea *sa = new QScrollArea(appWindow);
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setContentMargins(50, 50, 50, 50);
QWidget *widgetToScroll = new QWidget(sa);
widgetToScroll->resize(5000, 5000);
sa->setWidget(widgetToScroll);
QVBoxLayout *appWindowLayout = new QVBoxLayout(appWindow);
appWindowLayout->addWidget(sa);
appWindow->setLayout(appWindowLayout);
appWindow->show();
Snippet 2 (It's like setContentMargins() call is ignored completely):
QWidget *appWindow = new QWidget;
QScrollArea *sa = new QScrollArea(appWindow);
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setContentMargins(50, 50, 50, 50);
QGraphicsView *widgetToScroll = new QGraphicsView(new QGraphicsScene(sa), sa);
widgetToScroll->setAlignment(Qt::AlignLeft | Qt::AlignTop);
widgetToScroll->resize(5000, 5000);
sa->setWidget(widgetToScroll);
QVBoxLayout *appWindowLayout = new QVBoxLayout(appWindow);
appWindowLayout->addWidget(sa);
appWindow->setLayout(appWindowLayout);
appWindow->show();
Thanks.
To make the content margins work properly for a QScrollArea widget I subclass it and manually set the viewport margins (which is a protected method in QT 4.7)
// Extended class
class QScrollAreaWithMargins : public QScrollArea
{
public:
virtual void resizeEvent(QResizeEvent *event) override
{
// Define content margins here
setViewportMargins(5, 0, 0, 0); // <<<<< SET MARGINS HERE
QScrollArea::resizeEvent(event);
}
};
// Usage
//...
mEditorScrollArea = new QScrollAreaWithMargins();
//...
It looks like you are confusing the structure of how to nest a QGraphicsView and a QGraphicsScene. (Maybe it was just a typo?)
QGraphicsView *widgetToScroll = new QGraphicsView(new QGraphicsScene(sa), sa);
should be changed to
QGraphicsView *widgetToScroll = new QGraphicsView(new QGraphicsScene(), sa);
or
QGraphicsView *widgetToScroll = new QGraphicsView();
sa->setWidget(widgetToScroll);
When you add a QWidget to a layout, you change the widget's parent. When you set a widget (or QGraphicsView) to a QScrollArea, you change that widget's parent. See Object Trees & Ownership for more information. So if you wanted to set up your QGraphicsView inside a QScrollArea your code would look like this:
QWidget *appWindow = new QWidget;
QScrollArea *sa = new QScrollArea(); // No need to specify a parent here if
// you add it to a layout later
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setContentsMargins(50, 50, 50, 50);
QGraphicsView *widgetToScroll = new QGraphicsView();
widgetToScroll->setAlignment(Qt::AlignLeft | Qt::AlignTop);
widgetToScroll->resize(5000, 5000);
sa->setWidget(widgetToScroll); // This sets the parent for widgetToScroll
QVBoxLayout *appWindowLayout = new QVBoxLayout();
appWindowLayout->addWidget(sa); // This sets the parent for sa
appWindow->setLayout(appWindowLayout); // This sets the parent for appWindowLayout
appWindow->show();
As a side note...
When using QGraphicsViews with a QGraphicsScene, instead of setting the margins using a QScrollArea's setContentsMargins, I use the QGraphicsView automatic scrolling and just set the scene rect to have a larger margin that the size of my content like so:
QWidget *appWindow = new QWidget;
QGraphicsView *widgetToScroll = new QGraphicsView();
QGraphicsScene *scene = new QGraphicsScene();
scene->addRect(0,0, 5000, 5000);
widgetToScroll->setSceneRect(-50,-50, 5050, 5050);
widgetToScroll->setScene(scene);
QVBoxLayout *appWindowLayout = new QVBoxLayout(appWindow);
appWindowLayout->addWidget(widgetToScroll);
appWindow->setLayout(appWindowLayout);
appWindow->show();
The QGraphicsView includes quite a bit more than just automatic scrolling when needed. You can resize everything inside of it and quite a bit more. It is great for 2D layouts, interactions and animations. See Qt's Graphics View Framework at http://doc.qt.io/qt-5/graphicsview.html for more information.
Here is more information that may be useful when using margins and paddings: The Box Model used by QStyleSheets.