QScrollArea with a QWidget in a QSplitter - python-2.7

I´m making a project for my class, and I need to put a scrollArea in a widget (I choosed a splitter) and I want to push a button and create more scrollArea inside this widget. This is what I´ve done:
I create the button like this:
self.AddCanal = QAction(QIcon(), "Add channel", self, shortcut = "Shift+Ctrl+c", triggered = self.addChannel)
And I put it in a QToolBar().
Then, I create the scrollArea. I put the scrollArea with the Qwidget (in this case I use a QwtPlot) in a QSplitter (splitter1), and then I put a frame and the splitter in another splitter (splitter2). And at last, I put splitter2 and another frame in one last splitter (splitter3). You can see it here:
self.scrollLayout = QFormLayout()
self.canal = QwtPlot()
self.canal.setLayout(self.scrollLayout)
self.scrollArea = QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.canal)
self.scrollArea = QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.canal)
splitter2 = QSplitter(Qt.Horizontal)
splitter2.addWidget(self.frame)
splitter2.addWidget(splitter1)
splitter3 = QSplitter(Qt.Vertical)
splitter3.addWidget(splitter2)
splitter3.addWidget(self.frame_3)
I made it like this, because in one frame I will put a tree widget, and in the bottom frame i will put a QtextEdit().
Well, now I need that the button, when click it, creates another scrollArea in the splitter1. And I want to create at minimum 5 extra scrollAreas.
How can I accomplish this?

I solve it creating a method like this:
def addChannel(self):
global channelCount
self.scrollLayout = QFormLayout()
self.canal = QwtPlot()
self.canal.setLayout(self.scrollLayout)
self.scrollArea = QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.canal)
if channelCount <= 5:
self.splitter1.addWidget(self.scrollArea)
channelCount += 1
return channelCount
using "channelCount" as a global variable starting it in 1, just because i only want 5.
And i add:
self.addchannel()
at the QMainWindow class
Hope it can help somebody.

Related

Closing Popup and setting button label

I'm writing a C++ wxWidgets calculator application. I want to compress trigonometric function buttons into a single one to save on space, using what's basically a split button. If you left click on it, the current option is used. If you right click, a popup menu is opened, which contains all the buttons; when you click on one of them, it is used and the big button changes.
I've been suggested to use wxComboBox and other stuff for this job, but I preferred using wxPopupTransientWindow because this way I can display the buttons in a grid, making everything - in my opinion - neater.
Problem is, when I choose an option from the menu, the main button's ID changes (because when I reopen the menu the previously clicked button is light up as its ID and the big button's ID match), but the label does not. Furthermore, the popup is supposed to close itself when you left click on one of the buttons, but it does not.
This is the code for the custom button in the popup which is supposed to do all that stuff:
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxWindow* mBtn = this->GetParent()->GetParent();
mBtn->SetLabel(this->GetLabel());
mBtn->SetId(this->GetId());
this->GetParent()->Close(true);
}
}
This is the code for the custom button in the main frame which opens up the popup (temporary setup just to test if the whole thing is working):
void ikeButton::rightClick(wxMouseEvent& evt) // CREA PANNELLO ESTENSIONE
{
if (flags & EXPANDABLE)
{
std::vector<expandMenuInfo> buttons;
buttons.push_back(expandMenuInfo(L"sin", 3001));
buttons.push_back(expandMenuInfo(L"cos", 3002));
buttons.push_back(expandMenuInfo(L"tan", 3003));
buttons.push_back(expandMenuInfo(L"arcsin", 3004));
buttons.push_back(expandMenuInfo(L"arccos", 3005));
buttons.push_back(expandMenuInfo(L"arctan", 3006));
wxPoint p = this->GetScreenPosition();
size_t sz = this->GetSize().GetHeight() / 1.15;
expandMenu* menu = new expandMenu(this, buttons, sz, wxPoint(
p.x, p.y + this->GetSize().GetHeight() + 2));
menu->SetPosition(wxPoint(
menu->GetPosition().x - ((menu->GetSize().GetWidth() - this->GetSize().GetWidth()) / 2),
menu->GetPosition().y));
menu->Popup();
}
}
Let me know if I need to show more code.
This is probably a terrible way of doing this, but this is basically the first "serious" application I'm creating using the wxWidgets framework. Any help is appreciated.
when I choose an option from the menu, the main button's ID changes
(because when I reopen the menu the previously clicked button is light
up as its ID and the big button's ID match), but the label does not.
If you're creating the popup menu like in your previous post, you had a popup window with a panel as its child and the buttons were then children of the panel layed out with a sizer.
If that's still the case, this->GetParent() and should be the panel, this->GetParent()->GetParent() should be the popup. So this->GetParent()->GetParent()->GetParent() should be the trig function button (assuming you created the popup with the trig function button as the parent).
So I think the line wxWindow* mBtn = this->GetParent()->GetParent(); should be changed to wxWindow* mBtn = this->GetParent()->GetParent()->GetParent();.
Or slightly shorter wxWindow* mBtn = this->GetGrandParent()->GetParent();;
the popup is supposed to close itself when you left click on one of
the buttons, but it does not.
It looks like wxPopupTransientWindow has a special Dismiss method that is supposed to be used to close it.
So I think the line this->GetParent()->Close(true); should be changed to this->GetGrandParent()->Dismiss(); (Assuming as above that the buttons in the popup are children pf a panel).
Alternately, if you want a solution that will work regardless of the parentage of the controls in the popup window, you could have a utility function to find the popup ancestor which would look something like this:
wxPopupTransientWindow* FindPopup(wxWindow* w)
{
wxPopupTransientWindow* popup = NULL;
while ( w != NULL )
{
popup = wxDynamicCast(w, wxPopupTransientWindow);
if ( popup )
{
break;
}
w = w->GetParent();
}
return popup;
}
This uses the wxDynamicCast function which is slightly different from the c++ dynamic_cast expression. wxDynamicCast uses wxWidgets' RTTI system to check if the given pointer can be converted to the given type.
Then the mouseReleased method could use this utility function something like this:
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxPopupTransientWindow* popup = FindPopup(this);
if (popup ) {
wxWindow* mBtn = popup->GetParent();
mBtn->SetLabel(this->GetLabel());
mBtn->SetId(this->GetId());
mBtn->Refresh();
popup->Dismiss();
}
}
}
I'm not sure why you're setting trig function button to have a new id, but I assume you have a reason.
To make the SetLabel method work in your custom button class, I think the easist thing is to call the SetLabel() method in the button's constructor. This will store the string passed to the constructor in the button's internal label member.
Based on other questions, I think the ikeButton constructor looks something like this:
ikeButton::ikeButton(wxFrame* parent, wxWindowID id, wxString text,...
{
...
this->text = text;
To store the label, you would need to change the line this->text = text; to
SetLabel(text);
And when you draw the button, I think the method you use looks like this:
void ikeButton::render(wxDC& dc)
{
...
dc.DrawText(text, ...);
}
You would need to change, the line dc.DrawText(text, ...); to
dc.DrawText(GetLabel(), ...);
Likewise, any other references to the button's text member should be changed to GetLabel() instead.
Finally, when you set the label in the expandButton::mouseReleased method, it might be a good idea to call button's Refresh() method to force the button to redraw itself. I added that my suggestion for the mouseReleased method above.

qt treewidget widget item QCheckBox alignment

I have a QTreeWidget where I insert different widgets (QDoubleSpinBox,QSpinBox,QCheckBox...)
QTreeWidget *t = ui->treeWidget;
QTreeWidgetItem *item = new QTreeWidgetItem();
int c = 0;
QDoubleSpinBox *dspb = new QDoubleSpinBox();
t->setItemWidget(item, c++, dspb);
QSpinBox *spb = new QSpinBox();
t->setItemWidget(item, c++, spb);
QCheckBox *cb = new QCheckBox();
t->setItemWidget(item, c++, cb);
t->addTopLevelItem(item);
However, the cb widget looks wired since the checkbox is aligned to the left. I would like to see it aligned in the center.
Q: How can I change the checkbox to appear in the middle of the TreeWidget cell?
I need to be able to access the cb item again later. Currently, I use the following code:
QTreeWidgetItem *itm = t->topLevelItem(0);
bool checked = qobject_cast<QCheckBox *>(t->itemWidget(itm,c++))->checkState() == Qt::Checked;
If I need to do some workaround to get the central alignment going, how can I access the cb object then?
Found it:
cb->setStyleSheet("margin-left:50%; margin-right:50%;");
works!

How to fix the size of MDI Subwindow in Qt

I'm creating a Desktop Application in Qt and I'm showing subwindow inside the MDI Area. I have the problem that in the size of subwindow adjusts every time I open my code in the other monitor.
My goal is to fix the size of subwindow and make it parent size. Hope you understand my problem.
I'm using this code to change the size and showing the subwindow in mdi area
Subwindow1 = new QMdiSubWindow(mdiArea);
QQuickWidget* widget2 = new QQuickWidget(Map);
widget2->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget2->setSource(QUrl("qrc:/subwindow1.qml"));
widget2->show();
Subwindow1->setWidget(widget2);
Subwindow1->resize(700,640);
Subwindow1->setWindowTitle("Subwindow 1");
Subwindow1->setAttribute(Qt::WA_DeleteOnClose,false);
Subwindow1->setWindowFlag(Qt::FramelessWindowHint);
Subwindow1->addSubWindow(Subwindow1);
mdiArea->setActiveSubWindow(Subwindow1);
Subwindow1->show();
Subwindow2 = new QMdiSubWindow(mdiArea);
QQuickWidget* widget3 = new QQuickWidget(Camera1);
widget3->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget3->setSource(QUrl("qrc:/subwindow2.qml"));
widget3->show();
Subwindow2->setWidget(widget3);
Subwindow2->resize(304,270);
Subwindow2->setWindowTitle("Subwindow 2");
Subwindow2->setAttribute(Qt::WA_DeleteOnClose,false);
Subwindow2->setWindowFlag(Qt::FramelessWindowHint);
mdiArea->addSubWindow(Subwindow2);
mdiArea->setActiveSubWindow(Subwindow2);
Subwindow2->show();
Subwindow3 = new QMdiSubWindow(mdiArea);
QQuickWidget* widget4 = new QQuickWidget(Camera2);
widget4->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget4->setSource(QUrl("qrc:/subwindow3.qml"));
widget4->show();
Subwindow3->setWidget(widget4);
Subwindow3->resize(304,270);
Subwindow3->setWindowTitle("Subwindow 3");
Subwindow3->setAttribute(Qt::WA_DeleteOnClose,false);
Subwindow3->setWindowFlag(Qt::FramelessWindowHint);
mdiArea->addSubWindow(Subwindow3);
mdiArea->setActiveSubWindow(Subwindow3);
Subwindow3->show();
For example :
You have Subwindow1 with (700,640)
The code is : Subwindow1->setFixedSize(new QSize(700,640))
Hope it help !
https://doc.qt.io/qt-5/qwidget.html#setFixedSize

How to Add processBar inside QTreeWidget cloum

Is there any way in Qt to Add a processBar inside one of QTreeWidget items
Something like this
http://doc.qt.io/qt-5/qtreewidget.html#setItemWidget will do the job for you
just call it for each row with whatever widget you need.
cheers
/edit:
lets say your column 'status' has column index 5, then it would be something like this:
QTreeWidgetItem* item = new QTreeWidgetItem(columnTextsStringList);
/*insert into tree here*/
QProgressBar* progBar = new QProgressBar;
treeWidget->setItemWidget(item, 5/*column of the status*/, progBar);
// no need to delete progBar, its now a child of treeWidget
// use progBar

How to make a QMdiArea subwindow widget non-resizeable?

So the non-QMdiArea version of my code,
MyWidget::MyWidget(QWidget* parent)
{
...
layout()->setSizeConstraint( QLayout::SetFixedSize );
}
MainWindow::MainWindow(...)
{
...
MyWidget* wgt = new MyWidget(NULL);
wgt->show();
}
works just fine and produces a widget that the user can't resize. But when the MainWindow code is replaced with
MainWindow::MainWindow(...)
{
...
MyWidget* wgt = new MyWidget(ui->mdiArea); //Or MyWidget(NULL), same result
ui->mdiArea->addSubWindow(wgt);
}
the window, now within the QMdiArea, is resizeable. It doesn't seem to be an issue of Qt::WindowFlags, they don't handle resize policy. Surely there is a way to do this? NB I cant use something like setFixedSize(ht, wd) since the size of the widget can change programmatically (subwidgets are added and removed). But the user should not be able to resize it.
Even though MyWidget is not resizeable, when you call:
ui->mdiArea->addSubWindow(wgt);
The widget is put in a QMdiSubWindow which is resizeable. All you have to do is get the window that's created and fix its size:
QMdiSubWindow* subWindow = ui->mdiArea->addSubWindow(wgt);
subWindow->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
This should work, but I haven't tried this code myself.
EDIT: well... apparently that doesn't fix the size. :(
The following worked for me:
MyWidget* wgt = new MyWidget(ui->mdiArea);
QMdiSubWindow* subWindow = ui->mdiArea->addSubWindow(wgt);
subWindow->setFixedSize(wgt->size());
wgt->show();