Reorder widgets in Qt - user-interface

I would like to have suggestions as to how to use Qt to implement the following:
I have multiple identical widgets that I want to display once at a time.
I know that QToolbox exists, but the problem is the following:
I need to change the order in which the tabs or buttons appears (see image):
The widget that is set to an index does not stay at the same index, but should follow the header.
It doesn't have to be exactly as I describe, it's more the general idea of reordering my widgets that matters.
Thanks to all.

To change the order of the children, you can use QToolBox::removeItem() and QToolBox::insertItem(int index, QWidget *widget, const QString & text)
If you don't need random placement, but simply having the top widget moved to the bottom is sufficient, a couple of lines are enough to rotate the widgets :
QWidget *widget = toolBox->widget(0);
QString text = toolBox->itemText(0);
toolBox->removeItem(0);
toolBox->addItem(widget, text);

Related

Custom draw ListView Items without border per how TListView itself does it

In a custom control, I custom-draw TListView items myself in the TListView.OnAdvancedCustomDrawItem event. This works well.
I have been experimenting with several Theme classes and parts. For instance, when I use:
HTHEME Theme = OpenThemeData(Handle, L"Explorer::ListView") ;
DrawThemeBackground (Theme, Sender->Canvas->Handle, LVP_LISTITEM, LISS_NORMAL, &ItemRect, NULL);
I get what is to be expected, per Theme explorer (do notice the borders around the item):
But, if I look at a proper VCL TListView object, similar items are painted without a border. I expected this control to use the same Theme class and part. Is that not the case? If so, what class/part should I use to mimic the behavior?
This is what I see (notice the borders in the custom control vs the absence of borders in the true TListView control just below it:
I'm actually getting a 'nicer' result with LVP_GROUPHEADER, but I'm still very curious about LVP_LISTITEM.
FYI, using LVP_GROUPHEADER instead of LVP_LISTITEM. It works well for this type control, so a nice alternative, but I'm still very curious as to why the real ListView control paints no borders using LVP_LISTITEM (I THINK).
Perhaps I should add that I still use old C++ Builder 2009 for this project. This is a low effort attempt to improve the control to give it a life beyond W10 (Especially W11 where current MENU / MENU_POPUPITEM choice is not kind on the eyes). PS. having more problems with TPopupMenu now .. but that's another topic I guess.
A simple code example (not same as in project but showing the border):
#include "uxtheme.h"
#include "Vsstyle.h"
// Project includes uxtheme.lib
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HTHEME Theme = OpenThemeData(Handle, L"Explorer::ListView") ;
TRect ItemRect = Image1->ClientRect ;
DrawThemeBackground (Theme, Image1->Canvas->Handle, LVP_LISTITEM, LISS_NORMAL, (tagRECT*)&ItemRect, NULL);
CloseThemeData(Theme) ;
}
//---------------------------------------------------------------------------

Change color of background and title in MFC Control

I want to change text color and background color for my EDIT CONTROL, STATIC CONTROL and BUTTON CONTROL in MFC application. The control is in a CDialogEx dialogue .
I try to add the OnCtlColor (with wizard in visual studio, on the WM_CTLCOLR message) but I can't set the color of may static control and button control.
I put also a break point in the OnCtlColor function (in the IF construct), but I don't receive anything.
I also tried to use the SetTextColor function retrieving the handle of the control from GetDlgItem, but I can't change the color as I want.
Pleas help me.
I can assert that I tried to use in OnCtlColor in a CDialog and it worked for the static and for the edit controls.
All you have to do is:
For changing background color, you need to create a brush that still exists outside that function and return its HBRUSH with
return (HBRUSH) m_brush.GetSafeHandle();
So you have to make a variable (m_brush in this code) that is member or a static (I recommend the first), and in the dialog initialization you have to create the brush you want.
I thought maybe some controls will not work with this, and for those I also did
pDC->SetBkColor(RGB(0,0,255));
But seems to do nothing; it is in the code for safety.
For changing the text color,I did
pDC->SetTextColor(RGB(255,0,0));
These experiences worked well for edits and statics, but did not work at all for groupboxes!
Groupboxes are a strange entity in MFC, some kind of a platyplus: they are a CButton with the BS_GROUPBOX, but in this function, its nCtlColor is CTLCOLOR_STATIC instead of CTLCOLOR_BTN! I did this for them
UINT nStyle = (UINT)(pWnd->GetStyle() & 0x0F);
if(nStyle == BS_GROUPBOX)
{
return (HBRUSH) m_brush2.GetSafeHandle();
}
and what got painted was the little rectangle behind the groupbox title!
I could not get the text colour of groupboxes changed!
If you have groupboxes and it is really important to change their titles' text color, you can get the one from http://www.codeproject.com/Articles/29016/XGroupBox-an-MFC-groupbox-control-to-display-text and get its essential code parts: to be derived from CStatic, the OnPaint() and DrawItem() methods. Do not forget also the ON_WM_PAINT() on the message map. I don't know if the OnEraseBkgnd() and its is ON_WM_ERASEBKGND() message mapping are so essential.
It is also needed to change them to be Static text controls in the resources, declare a XGroupBox variable and do a DDX_Control of it.
I tested it and it really works.
For buttons, with CButtons it did not work. But, for each button, I simply declared a CMFCButton variable in the class and did a DDX_Control of each one. After, I had two choices:
Set its m_bTransparent property to TRUE in the form constructor (search this variable on afxbutton.cpp file for reference) for the ones I wanted to have the same color as the form (I also painted the form; in my case I was implementing themes on an application)
Set the Background color with SetFaceColor() and set the Text Color with SetTextColor() in form initialization.
When the CMFCButton does not have these things set, it got its color from theme blending of the currently selected CMFCVisualManager.
Note: I also replaced my CSpinButton entities with CMFCSpinButon ones, because I wanted colors from the selected theme.
In the OnCtlColor, the nCtlColor variable is important because it will allow you to personalize different colors to different types, without testing dynamic_cast success or failure for every control.
Do not forget to add ON_WM_CTLCOLOR() to your message map.
UPDATE 1:
After following the advice of the accepted answer on http://social.msdn.microsoft.com/Forums/vstudio/en-US/53f47162-078a-418f-8067-ee61a81ceeac/checkbox-transparent-color-not-working-in-vs2008?forum=vcgeneral , I did my own Groupbox class, and now it is like:
class CMyGroupBox: public CButton
{
protected:
virtual void PreSubclassWindow()
{
SetWindowTheme(*this, _T(""), _T(""));
#pragma comment(lib, "UxTheme.lib")
}
};
I just declared one of this, and did DDX_Control with its respective control ID, and now I can see the text in the color I supplied to SetTextColor. If you return a HBRUSH for this control, what gets painted is a non-filled rectangle drawn around the groupbox's title.
UPDATE 2: I just generalized the CMyGroupBox to be CMyButton, for using its PreSubClassWindow method not only in groupboxes, but also in checkboxes and buttons. In checkboxes it works well, in buttons, I am not so satisfied with the results.
UPDATE 3: I was trying to remove some weird effect on the rendering of the text and I just commented the pDC->SetBkColor(RGB(0,0,255)); line; the result was an ugly while rectangle behind the text :( . Then I replaced it with pDC->SetBkMode(TRANSPARENT); and I also see tht weird effect :(
UPDATE 4: In order to avoid to have to declare all my checkboxes, groupboxes and buttons as the class that contains the PreSubClassWindow method, I researched and discovered that it is not needed to do it. The code
SetThemeAppProperties(0);
#pragma comment(lib, "UxTheme.lib")
AfxGetMainWnd()->SendMessage(WM_THEMECHANGED, 0U, 0L);
disables theming for all controls at the whole application level.

Styling INDIVIDUAL cells in GAS FlexTable ...impossible?

It appears there is no way to style individual cells (to, say, change the background color of a header row, for example) within a GAS FlexTable. Is that correct?
The only methods I see here are .setStyleAttribute() and .setStyleAttributes() both of which operate on either the entire application or the entire flextable as the object.
Furthermore, I see no methods that return an individual cell or subset of cells from the flextable such as a .getCell() or .getRow().
Therefore, am I correct in concluding that there is no way at this time to set the style of an individual cell in a GAS flextable? (Sorry if the answer to this question is an obvious, “There is no way to do it.” But I figured I had better check with the experts first before giving up.)
setWidget is expensive
I pull out about 500X12 table in flextable and found use setText is at least twice times faster.
Then again, I also can not figure out how to change font size in flexTable while calling setText. The background, font color etc worked, but not font size.
Setting style to individual cell is done with:
method setStyleAttribute(row, column, attribute, value) - Sets a CSS style on a cell of this FlexTable.
You have to scroll down to the second occurence of setStyleAttribute on the FlexTable page. Since the HTML anchor is #setStyleAttribute for both methods you always get the first.
A getCell method would not be useful as a flextable cell is no widget.
There is also a setStyleAttributes(row, column, attributes) method ...
There is a very easy way to do this. Instead of using FlexTable.setText() to set the contents, use the FlexTable.setWidget() instead.
And you can add a label and style it however you want to and each label can have its own style

GTK: How to make labels as buttons (sort of list)

In GTK+ I would like to have a vertical list of labels, that a user can scroll. A user can click on any label and it will go to it's own callback function.
Right now I'm using a vertical area of buttons, but I really do not like having buttons. To give a good example, what I am trying to achieve would be considered very similar to a ListView in Android:
Is it possible to achieve this? I have tried replacing my buttons with labels but the signals stopped working (which would make sense). The GtkList is depecrated, and I am not sure what I am supposed to use instead?
I think you can use GtkTreeView with GtkListStore ( GtkTreeSelection for selection in GtkTreeView ). For scrolling of course you will make use of GtkScrolledWindow. Using GtkTreeView can be a little intimidating for a beginner but there are quite a few tutorial available online like this one. Also, if you can install gtk-demo application (part of gtk2.0-examples package on Ubuntu) which demonstrates using Gtk widgets along with code, it will be quite helpful for you.
Hope this helps!
What you could do as well (if you really want to use labels) is to just put each of them into a GTKEventBox, and then set the event mask to receive mouse clicks.
EDIT:
Example:
GtkWidget* gtk_clickable_label_new(const gchar *str)
{
GtkWidget *eventbox, *label;
label = gtk_label_new(str);
gtk_widget_show(label);
eventbox = gtk_event_box_new();
gtk_widget_add_events(eventbox, GDK_BUTTON_PRESS_MASK);
gtk_container_add(GTK_CONTAINER(eventbox), label);
return eventbox;
}
Have you tried putting your labels in a GtkVBox in a GtkScrolledWindow?
I think what you want is a bunch of GtkButtons that have no hieght/depth.
To do this use gtk_button_set_relief and choose the GTKReliefStyle of GTK_RELIEF_NONE.
That's how I put buttons in GtkTreeViewColumn headers, it looks nice.
Try it!

What Qt widget(s) to use for read-only, scrollable, collapsible, icon list

I'm relatively new to Qt, and am not entirely familiar with the out-of-the-box widgets. I have a somewhat (but not very) complex widget to create, and don't want to reinvent any wheels. What is the best QWidget to use as a starting point to subclass and/or QWidgets to use to compose my widget. Here is the end-result I am looking for (apologies for the crude drawing):
Key points:
All icons will take up the same size, say 128 x 128. Ignoring the category groupings, they should all align in a nice grid.
The widget should expand to fill all the horizontal and vertical area it can take. Expanding / shrinking horizontally may increase / decrease the number of icons shown in each row.
Icons are grouped, and those groups should be collapsible.
If the height of the widget exceeds its space, a vertical scrollbar should appear.
You're actually looking for some of the more esoteric options for a QListView/QListWidget.
At the top level, add QTreeWidget or QTreeView will give you the hierarchy you're looking for, as well as managing the scrolling area.
Each Listed Item of the (expanded) QTreeXItem will be a QListView/QListWidget, setting setViewMode(QListView::IconMode) on them.
EDIT:
Note that to get the precise look you wanted above, you'll probably have to use QListView and use a custom delegate, handling the drawing yourself (unless you can find a theme that will do exactly what you want). However, I've coded up a short PyQt solution below using the Q*Widget classes because they're shorter, and will still demonstrate how to get the right layout. If you're using C++, the same Qt function calls apply, but obviously you might have more or less bookkeeping.
import sys
from PyQt4 import QtGui, QtCore
class displayItem(QtGui.QWidget): #A simple widget to display, just centers a digit in a 100x100 widget
def __init__(self,num):
QtGui.QWidget.__init__(self)
self.size=100
self.resize(self.size,self.size)
self.setMinimumSize(self.size,self.size)
self.text = num
def paintEvent(self,event):
p = QtGui.QPainter(self)
p.drawText(self.size//2,self.size//2,str(self.text))
app = QtGui.QApplication(sys.argv)
widget = QtGui.QTreeWidget()
widget.setWindowTitle('simple tree')
#Build the list widgets
treeItem1 = QtGui.QTreeWidgetItem(widget)
treeItem1.setText(0,"TreeWidget Parent") #Sets the "header" for your [+] box
list1 = QtGui.QListWidget() #This will contain your icon list
list1.setMovement(QtGui.QListView.Static) #otherwise the icons are draggable
list1.setResizeMode(QtGui.QListView.Adjust) #Redo layout every time we resize
list1.setViewMode(QtGui.QListView.IconMode) #Layout left-to-right, not top-to-bottom
listItem = QtGui.QListWidgetItem(list1)
listItem.setSizeHint(QtCore.QSize(100,100)) #Or else the widget items will overlap (irritating bug)
list1.setItemWidget(listItem,displayItem(1))
listItem = QtGui.QListWidgetItem(list1) #Add a few more items
listItem.setSizeHint(QtCore.QSize(100,100))
list1.setItemWidget(listItem,displayItem(2))
listItem = QtGui.QListWidgetItem(list1)
listItem.setSizeHint(QtCore.QSize(100,100))
list1.setItemWidget(listItem,displayItem(3))
list1.setAutoFillBackground(True) #Required for a widget that will be a QTreeWidgetItem widget
treeSubItem1 = QtGui.QTreeWidgetItem(treeItem1) #Make a subitem to hold our list
widget.setItemWidget(treeSubItem1,0,list1) #Assign this list as a tree item
treeItem2 = QtGui.QTreeWidgetItem(widget) #Make a fake second parent
treeItem2.setText(0,"TreeWidget Parent II")
widget.show() #kick off the app in standard PyQt4 fashion
sys.exit(app.exec_())

Resources