Make two QDockWidgets mutual execlusive at the same position - qt

I have two QDockWidget's, only one of them is visible at the time, I manage that by toggleViewAction().
What I need to do is that I want the two QDockWidget's to be in the same location, with the same size and docked at the same dockWidgetArea with the same orientation and order relative to other QDockWidgets.
I did most of the that by this code:
void myMainWindow::slotToggleDocks(QAction* action) {
if(action == viewDock1) {
Dock1->setFloating(Dock2->isFloating());
Dock1->resize(Dock2->size());
Dock1->restoreGeometry(Dock2->saveGeometry());
Dock1->move(Dock2->pos());
addDockWidget(dockWidgetArea(Dock2), Dock1);
...
Dock2->hide();
} else if(action == viewDock2) {
Dock2->setFloating(Dock1->isFloating());
Dock2->resize(Dock1->size());
Dock2->restoreGeometry(Dock1->saveGeometry());
Dock2->move(Dock1->pos());
addDockWidget(dockWidgetArea(Dock2), Dock1);
...
Dock1->hide();
}
}
this code make the two have the same location and size and docked to the same area (left, right, ...) but it doesn't guarantee that the Docks will have the same layout with the other QDockWidget's in the same dockWidgetArea.
Meaning if this was the before layout:
Layout before http://holmez.net/qdockwidget/1.png
This is after toggling:
Layout after toggling http://holmez.net/qdockwidget/2.png
This is what I want:
Expected result http://holmez.net/qdockwidget/3.png

I managed to do that by a simple trick, add this line of code:
splitDockWidget(Dock1,Dock2,Qt::Horizontal);
before hiding Dock1, and this line:
splitDockWidget(Dock2,Dock1,Qt::Horizontal);
before hiding Dock2.
This fixed the problem of the arrangement of docked widgets, not sure if this is the best way but it works for me.

What about only using 2 QDockWidgets, but having QStackedWidgets INSIDE of them which you can use to swap views? That's what I'm currently doing, and it works great.
Another advantage is that swapping views is as simple as:
stackedWidget->setCurrentIndex(index);

What about using QTabWidget?
The 2 widgets will have to be in the same Qt::DockWidgetAreas

Related

Problems changing the flags of a QWidget

I have a QWidget as the child of another within my application. The task consists of putting the internal widget in full screen mode and being able to see it again in normal mode with the same button. This partly I have managed to do it in the following way:
if(!isFullScreen())
{
setWindowFlags(windowFlags() | Qt::Window);
showFullScreen();
}
else
{
setWindowFlags(windowFlags() & ~Qt::Window);
showNormal();
activateWindow();
}
The problem arises when you return to see the widget in normal mode. Things that happen:
The mouse cursor stays with pointing hand cursor.
The button to change mode remains in hover state (the background color is changed when the mouse is over)
Passing the mouse through other widget controls does not change its appearance
I have to click on the widget to fix the behavior. It's as if the widget did not receive events of any kind or something like that. I tried calling setFocus () and it did not work. I have also tried to send an event by hand in the following way but it has not worked either:
QMouseEvent my_event(QEvent::MouseButtonPress, QPointF (0, 0), Qt :: NoButton, 0, 0);
QApplication::sendEvent(this, & my_event);
Any ideas?
Thanks.
Cannot reproduce your issue on Xubuntu with Qt5.9.4.
However I did the same in my last job, and it worked correctly on all platforms. It was something like this, I think:
if(!isFullScreen())
{
setParent(0);
showFullScreen();
}
else
{
orignalParentLayout->addWidget(this); // better: insert at correct position
showNormal();
}
For this you have to add some knowledge about the parent's layout though. You could try to detect that info before going into full screen mode, but it is probably not worth the effort.
You could also try:
if(!isFullScreen())
{
logicalParent = parentWidget();
setParent(0);
showFullScreen();
}
else
{
setParent(logicalParent);
showNormal();
}
If you have no layout. You might also want to store the geometry before going to full screen.

Customizing ViewPagerIndicator style

In my app, I am trying to style ViewPagerIndicator. The pager consists of several fragments. I want something exactly like the picture attached - the CirclePageIndicator at the bottom right & a title at the bottom left. However, the CirclePageIndicator is positioned centered by default & if I customize indicator's "centered" value false, then it goes to the left. I haven't found any option to move that to the right side as shown in the picture.
Another concern is the title of the pager. I have tried with PagerTitleStrip but this is not actually what I am looking for, this PagerTitleStrip shows the previous & next page's title at the left & right side of the title, but I want only this page's title - exactly in the same format like the picture.
BTW, I am using Jake Wharton's library for the ViewpagerIndicator.
I am stuck in this issue for several days. I hope someone comes out with his wise thinking & helps me out of this?
Regards. & Thanks in advance.
In src / com / viewpagerindicator / CirclePageIndicator.java
add this
//at line 236
if (mRight) {
longOffset = longSize - ((count * threeRadius) / 2.0f);
}
//at about line 116
public void setRight(boolean right) {
mRight = right;
invalidate();
}
//line 58
private boolean mRight;
you could also add some padding if you wanted

fragments, android:zAdjustment (z order) and animations

I'm using the support library. Now, I want to have a fragment shifting in from the bottom, moving OVER the previous one.
For this I use this to keep the previous fragment (the one that is being slided over) visible until the new fragment is in its place:
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="2500"
android:zAdjustment="bottom" />
this is animation used for the new fragment to slide in from bottom:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%p" android:toYDelta="0"
android:duration="#android:integer/config_mediumAnimTime"
android:zAdjustment="top"/>
I've put the z adjustment to bottom and top for both, but still the 'bottom' animation is still on top of the new fragment! I have put the duration to 2500 for testing and it stays on top for the whole time.
Does zAdjustment not work for fragment animations?
According to this google group thread Z adjustment only works for window animations.
"The Z adjustment only works for window animations. I thought this was documented, but apparently not."
-- Dianne Hackborn (Android framework engineer)
You can override the onCreateAnimation method and for any animations you can check what animation is currently running and if you need it to be on top, set the Z-axis from there.
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
if (nextAnim == R.anim.enter_from_right || nextAnim == R.anim.exit_to_right) {
ViewCompat.setTranslationZ(view, 1f)
} else {
ViewCompat.setTranslationZ(view, 0f)
}
return super.onCreateAnimation(transit, enter, nextAnim)
}
Recommend implementing this as a base Fragment class for all your fragments.
I've also got stuck with that problem. So instead of using transaction.replace(containerId, newFragment) I've created two containers for fragments and now my code looks like this one
Add first fragment:
transaction.add(containerId1, firstFragment).commit();
Add second fragment with animation over the first one:
findViewById(containerId2).bringToFront();
transaction.setCustomAnimations(R.anim.slide_in_up,
R.anim.stay).remove(oldFragment).add(containerId2, newFragment).commit()
You can use androidx.fragment.app.FragmentContainerView as a fragments container. It automatically handles z order for animations specified in setCustomAnimations()

fixing child layout/widget position in QT

I wanted to know whether is there any way of fixing child layouts within a parent layout. For example...
QVBoxLayout *vbox = new QVBoxLayout;
// adding pushbuttons/layouts...
vbox->addWidget(one);
vbox->addWidget(two);
vbox->addWidget(three);
vbox->addWidget(four);
Now this ends up as four buttons/layouts in a vertical layout in the sequence that they are added. But if I remove buttons/layouts "one", "two" and "three"...
vbox->removeWidget(one);
vbox->removeWidget(two);
vbox->removeWidget(three);
After doing this, the pushbutton "four" will move up the layout as you remove widgets on top of "four". I don't want this to happen.
Is there any way that even if I remove the widget/layout on top, I need that last widget/layout to stay where it is currently.
How do I achieve this ?
UPDATE: Well I was experimenting and I was kind of able to achieve what I wanted using QGridLayout. Here is the code, but I am using QGridLayout instead of QVBoxLayout.
connect(one,SIGNAL(clicked()),this,SLOT(remove_btns()));
g = new QGridLayout(this);
g->addWidget(one,0,0,1,2);
g->addWidget(two,1,0,1,2);
g->addWidget(three,2,0,1,2);
g->addWidget(four,3,0,1,2,Qt::AlignBottom);
setLayout(g);
If I delete the above three buttons, the fourth one stays where it is, because of QT::AlignBottom , it does not work without that thing.
Here is the SLOT remove_btns()
void test::remove_btns()
{
g->removeWidget(one);
g->removeWidget(two);
g->removeWidget(three);
delete one;
delete two;
delete three;
}
When I click "one", top three buttons vanish, and the fourth one stays where it is. But it does not work if I don't give the QT::AlignBottom . Also, these alignment things are a mystery to me, I am unable to find how exactly they work.
This is definitely NOT an answer..., because I don't understand how it worked :P
If you are immediately replacing the widgets you removed, you can always insert your new widgets by index.
void insertWidget ( int index, QWidget * widget, int stretch = 0, Qt::Alignment alignment = 0 )
Yes, just hide the widgets instead of removing them:
one->hide();
two->hide();
three->hide();
If you really have to remove the widgets, perhaps you can replace them with some lightweight widget like a QLabel with no text.

Qt4 expanding tabs in QTabBar

I am subclassing QTabWidget to add a QTabBar, who's tabs stretch over the whole width of the tabBar. Therefore I am setting the expanding property to true. This doesn't seem to change anything about the behavior of the tabs.
Did anyone encounter the same problem? I use Qt 4.6 in combination with
TabWidget::TabWidget(QWidget *parent)
{
tabBar = new QTabBar(this);
tabBar->setIconSize(QSize(160,160));
tabBar->setExpanding(true);
setTabBar(tabBar);
}
EDIT: has been solved, here is how I implemented it, in case anyone is interested:
tabBar = new QTabBar(this);
tabBar->setExpanding(true);
layout = new QVBoxLayout(this);
setLayout(layout);
stackedLayout = new QStackedLayout();
layout->addWidget(tabBar);
layout->addLayout(stackedLayout);
connect(tabBar, SIGNAL(currentChanged(int)), stackedLayout, SLOT(setCurrentIndex(int)));
void MainWindow::addTab(QWidget *widget, const QIcon &icon, const QString &label) {
tabBar->addTab(icon, label);
stackedLayout->addWidget(widget);
}
From the QTabBar source code:
// ... Since we don't set
// a maximum size, tabs will EXPAND to fill up the empty space.
// Since tab widget is rather *ahem* strict about keeping the geometry of the
// tab bar to its absolute minimum, this won't bleed through, but will show up
// if you use tab bar on its own (a.k.a. not a bug, but a feature).
To get around this "feature", you can create your own tab widget using a QTabBar above a widget with a QStackedLayout.
5.2.0 onwards
QTabWidget::tab-bar {
min-width: 999999px;
}
It will work. No need to use any combination. You can use QTabWidget. Daniel ans is correct.
Building on #baysmith's answer, an easier way to force the QTabWidget to let the QTabBar expand, is to set a stylesheet on your QTabWidget that looks something like this:
QTabWidget::tab-bar {
width: 999999px;
}
Or another ridiculously large number. If your QTabWidget has the tabs going vertically instead of horizontally, use 'height' instead:
QTabWidget::tab-bar {
height: 999999px;
}
This seems to work fine for me, with Qt 5.0.1. The tabs expand to fill the space, each getting an equal portion. However, it seems like they intentionally leave enough empty space for one more tab, regardless. But the rest of the space is filled as desired. The empty space might be reserved for the tear/scroll buttons, incase too many tabs get added - but I'm not sure.

Resources