This question already has answers here:
change active form to show another form
(4 answers)
Closed 9 years ago.
Is there a way to make it so that, when I click a button, instead of needing to bring up a new dialog for my next screen, it just 'replaces' what's on the screen? (For instance, the default screen is a main menu with some buttons, which lead to more in depth screens, like Parts Inventory, and all of it's options now being on the screen).
In the realm of stacking panels, how efficient is this for a larger system? I need at least 30-40 screens going on.
Edit: I'm using Visual Studio 2010 to do this project for school, and using Windows 7 with the default packages.
Instead of creating a new forms for each screen you can create a new user control for each screen. Then you could have one form with a panel and loading the control into the form instead of creating a new form showing it and hiding the old one. Youcould do something like this:
...
MyControlWasForm1 form1 = new MycontrolWasForm1(); // this is a user control
panel1.Controls.Clear();
panel1.Controls.Add(form1);
...
You could also keep references to the old control if you want to be able to go back then just reload it into the panel.Controls when needed. Keep in mind if you don't have a variable referencing the control outside of the method, then when you remove it from the controls it would get garbage collected.
...
//property on main Form
public MyControlWasForm1 Form1 { get; set; }
...
//in method
if(Form1 == null) Form1 = new MycontrolWasForm1(); // this is a user control
panel1.Controls.Clear();
panel1.Controls.Add(Form1);
...
You can use multiple panels stacked and show/hide them depending on what you want to display
Related
I have a program that when I click the "next" button, another window appears with the same form or other components appear.
I tried to add a panel on the main form with two buttons "home" and "next" and then a panel where you can see other forms to give the feeling that the page is changing. In the constructor I try to pass the previous form and the main one so that when clicked it returns to it with all its elements.
DesktopReserve formPadre;
DesktopPrincipal deskPrincipal;
public Form1(DesktopReserve formPadre, DesktopPrincipal deskPrincipal)
{
InitializeComponent();
this.formPadre = formPadre;
this.deskPrincipal = deskPrincipal;
this.deskPrincipal.returnButton.Click += new System.EventHandler(this.returnButton_Click);
}
I understand that this is not the best way to do it. Apart from the fact that when I show the different forms within this panel it shows in another size, I would like to know a more efficient way to execute this.
I'm trying to make a WindowsFormApplication in Visual Studio 2015 and need some help.
I've been trying to search for the answer on internet but can find out how to do the following:
I have two windows (solutions?). I open the second window with a button in the first one with this code:
this.Hide();
intermec prodinter = new intermec();
prodinter.ShowDialog();
My question is:
How can i "include" the second window (like "include" in PHP) instead of close the first window and then open the next one, like it does now?
A Form is just another Control. Think of it as a Container (because it holds other Controls).
A User Control can also hold more than one Control. There are ways you can display a Window inside another Window in a WinForms app, but the desired effect is not always guaranteed. So it would be best to place all of your controls (for "page 1", for example) in a User Control called "Page1", and then, when appropriate, add that User Control to the Form, and set its Dock property to Fill.
And when it's time to show a different "page", Hide(); "Page1", and Show(); "Page2".
I think you are talking about form inheritance:
Just create a form, lets call it as frmBase. And add some controls onto frmBase which you want to have on other forms as well.
Create other form, lets call it as frmDerived.
In the code behind of frmDerived, just do the following:
// derive the frmDerived form from frmBase
public partial class frmDerived : frmBase
{
public frmDerived()
{
InitializeComponent();
}
}
And then just check the frmDerived form design, it should include everything from frmBase.
And you may want to make the access modifier of some controls of frmBase to Public as required to access them on frmDerived.
I hope this will help you. :)
For those who are very familiar with C# or VB.NET using the UserControl component in the .NET Framework (which is the hottest framework in my opinion), you were used to adding several buttons that preview different user controls as follows:
1) First you would prepare an appropriate user interface (contains 3 buttons and a single panel on the right area to view each user control after clicking one of the added buttons).
2) Adding 3 user controls from the solution explorer...
3) Inserting the content on each user control...
4) Implementing code for the 3 buttons on the frmMain.cs as the following (for this implementation we will be implementing the "Welcome" button carrying the object name as welcomeBtn, and the rest will have identical code but different user control names instead):
private void welcomeBtn_Click(object sender, EventArgs e)
{
//Clear up everything from the panel if any item exist(s)...
mainPanel.Controls.Clear();
//Create a new instance of a user control for the button...
UserControl1_Welcome welcome = new UserControl1_Welcome();
//Show up the created instance of the user control
mainPanel.Controls.Add(welcome);
}
5) Finally, the program will end up initially like this when running:
http://i.stack.imgur.com/OENwG.png
** Usage of the program **
When you click on the "Welcome" button for example, the result should be expected to be like this:
http://i.stack.imgur.com/iCyo3.png
... and when you click on a different button, lets say "License Agreement" button, you would expect to see something other than your current selection.
MAIN QUESTION
How can we bring the simplicity of Windows Forms in QT CREATOR by applying the "QDockWidget"?
I have tried inserting the QDockWidget component with no problems, but when I try to do the equivalent .NET code for adding the QWidget inside the QDockWidget:
ui->dockWidget->setWidget(myWidget);
which I think is equivalent to this line of code in C#.NET (correct me if I'm wrong here):
ui.Controls.Add(myWidget);
After using this code, my program won't crash nor shows anything running...
P.S. I'm sorry for linking the images, I don't have 10 reputation for making them show up...
What I want is to have a program that does the same thing with the C# example (showing a user control based on the click of a button).
If you want to show a particular widget based on a button click, I suggest to use a QStackedWidget
A simple example would be like this:
// In the constructor of your CustomWidget
// Create your buttons
QPushButton* firstButton = new QPushButton("First Button", this);
QPushButton* secondButton = new QPushButton("Second Button", this);
QPushButton* thirdButton = new QPushButton("Third Button", this);
// Create your (custom) widgets
QLabel* firstPageWidget = new QLabel("First Label", this);
QLabel* secondPageWidget = new QLabel("Second Label", this);
QLabel* thirdPageWidget = new QLabel("Third Label", this);
// Add them to the stackWidget
/*QStackedWidget* */ m_stackedWidget = new QStackedWidget(this);
m_stackedWidget->addWidget(firstPageWidget);
m_stackedWidget->addWidget(secondPageWidget);
m_stackedWidget->addWidget(thirdPageWidget);
// Insert buttons and stackWidget to CustomWidget
QVBoxLayout* layoutStack = new QVBoxLayout();
layoutStack->addWidget(m_stackedWidget);
QVBoxLayout* layoutButtons = new QVBoxLayout();
layoutButtons->addWidget(firstButton);
layoutButtons->addWidget(secondButton);
layoutButtons->addWidget(thirdButton);
QHBoxLayout* layout = new QHBoxLayout();
layout->addLayout(layoutButtons);
layout->addLayout(layoutStack);
setLayout(layout);
// Connect button clicks to slots
connect(firstButton, SIGNAL(clicked()), this, SLOT(onFirstButtonClicked()));
connect(secondButton, SIGNAL(clicked()), this, SLOT(onSecondButtonClicked()));
connect(thirdButton, SIGNAL(clicked()), this, SLOT(onThirdButtonClicked()));
Then you change the currently visible widget in the slots:
void CustomWidget::onFirstButtonClicked() {
m_stackedWidget->setCurrentIndex(0);
}
void CustomWidget::onSecondButtonClicked() {
m_stackedWidget->setCurrentIndex(1);
}
void CustomWidget::onThirdButtonClicked() {
m_stackedWidget->setCurrentIndex(2);
}
Note that if you want the button clicks just to simply change some text (as opposed to change the visible widget), you probably better use a QTextEdit instead of a QStackedWidget, and in the slots call setText("....");
If you have a lot of buttons, you'd better use QSignalMapper to limit the number of slots.
Also, I didn't get why you mentioned QDockWidget since they have a quite specific usage:
The QDockWidget class provides a widget that can be docked inside a QMainWindow or floated as a top-level window on the desktop.
QDockWidget provides the concept of dock widgets, also know as tool palettes or utility windows. Dock windows are secondary windows placed in the dock widget area around the central widget in a QMainWindow.
If you simply want a separate window, you're probably looking for a QDialog
How to do this with QtDesigner:
First you would prepare an appropriate user interface (contains 3 buttons and a single QStackedWidget on the right area to view each user control after clicking one of the added buttons).
Adding 3 pages for the user controls in the stack (+ one for the "empty" page if you really need that). If you want to design the Controls in separate UI Files / Only in Code (instead of all controls in your MainFrame), you would add plain QWidgets and promote them to the appropriate specific widget type
Inserting the content on each user control...
Implementing code for the 3 buttons on the frmMain.cpp/.h as the following (for this implementation we will be implementing the "Welcome" button carrying the object name as welcomeBtn, and the rest will have identical code but different user control names instead):
void FrmMain::on_welcomeBtn_clicked() {
ui->stack->setCurrentWidget(ui->welcomeWidget);
}
Select the "empty" page at as the current page in the designer, so the program will end up initially like this when running: (your screenshot)
When you click on the "Welcome" button for example, the result should be expected to be like this: (your second screenshot)
In my opinion, Miki's answer is the only correct approach to this use case (using a QStackedWidget).
For sake of completeness, I'll demonstrate how the same Clear and Add method as used in .NET is done in Qt:
// Assume controlPanel is a QWidget where you want to place the items
// Assume that controlPanel has set a layout (e.g. QHBoxLayout)
// Clear: Remove all Items from layout
QLayoutItem *child;
while ((child = controlPanel->layout()->takeAt(0)) != NULL) {
delete child;
}
// Now widgets are still there, but not layouted. Delete them explicitly
foreach (QWidget * w, controlPanel->findChildren<QWidget*>()) {
w->deleteLater();
}
// Now controlPanel is cleared
// Add new control
controlPanel->layout()->addWidget(new MyNewControlWidget);
First is, we can not force how other framework works to another one. Each framework has its flow and design.
What I am understand is you want to show another widget to the main window.
If you want to use the QDockWidget, its says on the documentation like this :
void QDockWidget::setWidget(QWidget * widget)
Sets the widget for the dock widget to widget.
If the dock widget is visible when widget is added, you must show() it explicitly.
Note that you must add the layout of the widget before you call this function; if not, the widget will not be visible.
Please share here you code of myWidget, so we can try to help you to figure out what is wrong.
On my side, I can achieve it by add the QVboxLayout on your ui->dockwidget and add QLabel with emtpy string and when you want to show myWidget just call ui->dockwidget->vboxlayout->replaceWidget(label, myWidget);
So I'm trying to learn a thing or two about coding with c# and something i find quite annoying is the way to switch between forms.
Lets say for a game you want to go to the options panel and when you click the button to get there it closes that window(form1) and opens a new window(form2) for my app.
It doesn't look very nice having windows opening and closing like that so I'm wondering what i can do in order to make it switch from form1 to form2 without closing form1 and not open form2 in a new window (Everything switched on the main window(form1).
Might sound a bit confusing but hopefully you understand what i mean.
The code I'm using so far to switch between forms:
ChangeOptions optionchanger = new ChangeOptions ();
this.Hide();
optionchanger.Show();
You could add two panels to a single form, each of which contains the controls you would otherwise have added to one of the two forms. Then switch between the panels by changing their visibility or Z-order. This is slightly tricky in the Windows Forms Designer because you'll have to design the two panels, then position them in the same spot on the containing form.
As #ryanyuyu points out, you can set the Dock property to DockStyle.Fill and switch which panel is on top using Control.BringToFront or Control.SendToBack(). This is also a decent way to interact with the two panels in the designer, as you can switch which is on top from a context menu option.
To truly have two forms, your only option is to show a dialog. Hiding your current window is of course optional.
However, you can:
Group all the controls on a given "form" into a Panel or GroupBox, then show/hide the container control.
Put all the controls into UserControls and have an instance of each UserControl on the main form. You can then show/hide the control.
I prefer the second method as it keeps the encapsulation tighter. Since you already have two forms, its easy to convert to user controls.
Does a Winform Framework exist for something similar to ASP.NET Masterpage or MS Access SubForm ?
With MS Access SubForm you can do like ASP.NET Masterpage. It's a huge loss of time with Winform when having to create a lot of complex form. You have to compensate with either Code Generation which create code duplication or do Runtime Dynamic Form which is much more difficult.
I searched on the Internet but can't find any.
The closes thing to Master Pages is Form Inheritance. It is regular class inheritance but also supported by the Designer. To try it:
1) Add a form with Ok and Cancel Buttons, Build project (essential)
2) Choose Project, Add new item, Windows and then the Inherited Form template. Pick the Form from step 1) as the base Form. Add some controls.
3) Repeat step 2) a few times
4) make some Buttons to show the Forms, Build and Test
5) Go back to the Form from 1) and change a few things (Background), run again
Your other tool are UserControls, they work much the same as in ASP.NET. You develop them like Forms and apply them as Controls.
You can add forms to a form, or to a panel on a form.
public Form1()
{
InitializeComponent();
Form2 embeddedForm = new Form2();
embeddedForm.TopLevel = false;
Controls.Add(embeddedForm);
embeddedForm.Show();
}
You will need to set the FormBorderStyle to None, unless you want to have an actual moveable form inside your form.
I was in a bit of a hurry at the time of posting, but Henk is right. You should consider creating a user control for this instead. Not to be confused with a custom control, which is intended for when you need to do your own drawing instead of using collections of standard Windows controls.