I have 3 grouped Tool Buttons (a Tool Bar). One of them is always down. And I have 3 frames. What is the easiest and right way to change the frames switching among the buttons?
Thanks!
The right way is moot at best. One of the easiest ways of many can be to set unique Tags for the grouped buttons, f.i. 0, 1, 2, then set all of the three button's 'OnClick' to the same handler and show one of your frames according to the tag of the clicked button and hide the others:
procedure TForm1.ToolButton1Click(Sender: TObject);
begin
Frame1.Hide; // will return immediately if already hidden
Frame2.Hide;
Frame3.Hide;
case TToolButton(Sender).Tag of
0: Frame1.Show;
1: Frame2.Show;
2: Frame3.Show;
end;
end;
This is assuming you've already put the frames on your form at design time. Don't forget setting the Grouped property of the buttons and their Styles to 'tbsCheck'.
If the frames are all in the same position on the screen, then doing it the way the Sertac suggests will make it really cumbersome to see in the IDE what they look like on their owner form
I suggest you put the frames in a page control or tab control.
Related
I have been away from Delphi for a few years, doing web apps.
I have gotten used, in HTML of just declaring successive <div> ... </div> and having them placed below each other, with spacing provided by CSS.
I want to do a Delphi app where I have a collection of data, let's say it's data about movies. Initially, I would have a panel for each , showing only the title. If you click one, it will expand to show actors, director, plot summary, etc. Click another and the first will shrink & the new one expand (max one expanded; click that one again to shrnkk it).
So, I have two layout problems: 1) to calculate the initial .top of each panel and 2) to re-calculate as different panels are clicked.
I am quite capable, of course, of coding all of this manually, but it seems tedious and error prone.
Is there an accepted way to do this? A VCL component that comes with Delphi? Should I be asking on https://softwarerecs.stackexchange.com/ for a 3rd party VCL component?
The closest VCL control is probably TCategoryPanelGroup, which is composed of vertically aligned expandable panels (TCategoryPanel).
The control does not have an 'autocollapsepanels' or 'maxexpandedpanelcount' property, but you can use some simple code to achieve the required behavior.
E.g. the below OnExpand event handler, if attached to all category panels in the group, will cause an expanded panel to close others.
procedure TForm1.CategoryPanelExpand(Sender: TObject);
var
I: Integer;
begin
if Sender is TCategoryPanel then
for I := 0 to CategoryPanelGroup1.Panels.Count - 1 do
if CategoryPanelGroup1.Panels[i] <> Sender then
TCategoryPanel(CategoryPanelGroup1.Panels[i]).Collapse;
end;
You can set AlignWithMargins property of your panels to true, then adjust spacing by using the Margins properties of the panels.
I am running Lazarus 0.9.30.2.
I have a TForm on which there is a TPageControl. Within the TPageControl there is a series of TTabSheets. At runtime the order of the TTabSheets differs from design time (see picture).
The order in design time is what I want to see at runtime, at least for the very first time the form is displayed. Why does the order change at run time and is there a way to control this?
#TLama is correct that this is related to way the Windows tab control behaves when in multi-line view. The behaviour you are observing is related to the way selection is handled for multi-line tabs. When you select a tab it is always shown in the bottom row because the visual cue to indicate which tab is selected can only really work for tabs in the bottom row.
Given that constraint the control simply has to rearrange rows of tabs as you modify the selected tab. It's astoundingly confusing for the user. Good UI design never has UI elements changing position like this.
Clearly what is happening here is that the rearrangement is happening at runtime when the form is first shown and for whatever reason this is resulting in a different arrangement from the design time arrangement. Given that the user can arrange the rows in any order just by selecting them I'm not sure you should worry about what order the rows appear in.
If you are dead set on forcing a particular arrangement when the form first shows you can add code like this to a OnCreate handler for the form:
PageControl1.ActivePage := TabSheet9;
PageControl1.ActivePage := TabSheet5;
PageControl1.ActivePage := TabSheet1;
Best practise for UI design is to avoid multi-line tab controls and I urge you to attempt to re-design your UI that way.
Please help me with my question.
I have TreeView and Frames, how can I shift them if I click on an item of TreeView?
Is it better to use PageControl (PageControl1.Pages[i].TabVisible := false;) instead of Frames or Frames fit better?
Thank you very much!
To answer your first question "how to ... using a TreeView?" : Implement the OnChange event of the TreeView. The node parameter refers to the newly selected item.
About your second question "Should I use Frames or a PageControl?" : Well, one does not exclude the other and you perfectly can use both. Indeed, I advice to do so when you use the contents of such a TabPage multiple times. In those cases, place the Frame with Align = alClient on your TabPage.
Frames are usefull to design an arbitrary reusable container. For instance: you could set the same FrameType on every Page of the PageControl, assuming they all look the same but each working with different data.
Another possible minor advantage of using frames is not to get confused about all the controls on the TabPages.
But if every TabPage is unique in terms of visual style or control layout, then it's perfectly ok to not use frames and design the pages on the PageControl directly.
And about the shifting part: I don't exactly understand what you want to accomplish by setting the visibility of a tab, but shifting to another page (depending entirely on your implementation) based on the node could be as simple as:
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
PageControl1.ActivePageIndex := Node.Index;
end;
I'm looking for a way of implementing a sort of inset caption before a set of tabs, something like this:
The tab set is not supposed to be multi-line, will only be horizontal and laid out at the top. However it should be correctly scrollable when there are too many tabs.
I fear I'm going to be restricted here with regard to using third-party controls, but I could use subclassing on the standard TTabControl to add the necessary changes to the standard looks and behaviour. (I don't need it to be TPageControl, because it's only the specific arrangement of the tabs that I am interested in.)
Maybe there's some way of implementing this with craftily arranged combination of standard controls, which, despite my endevours, has escaped me.
Basically, any ideas or pointers are welcome.
Oh, and additional requirement is, it should blend well with desktop themes.
Granted some time has passed, but I recently needed this style and found you can do it with the TMS Software TAdvOfficePager. It has a property FixedTabs, which I set to 1 in this case. It also has an OnChanging event where you can prevent access to a tab, in this case I used AllowChange := (ToPage > 0); Lastly, I set the first tab to disabled.
Then just style the first tab different than the rest and you can have something like this:
Have you tried to make the first tab to be the caption you want.
With some additional logic you can restrict the selection of this tab.
I don't know if you can control the style of each tab individually to make the first one look as it is not the tab.
Here is crafty arrangement of controls that will work. I have done this sort of thing in the past. Best of all it automatically handles scrolling of tabs.
I have an application that uses a frame extensively and needs to hide/show certain buttons depending on which form is active at the time. In order to keep the buttons neat and organized appropriately, I have put them on panels and show or hide the panels as needed for each form. My problem is when each form is initially created, the panels on the frame are out of order even though I am explicitly telling them which order to put themselves into. After I hide and re-show the form, the panels are in the correct order. Any suggestions on how to keep them in the proper order from the very beginning?
Instead of giving the panels explicit positions, try giving them alignments. They tend to stick better than way, and they do a better job of resizing if you resize the form.
You can also try using a stackpanel (or was it flowpanel?) as parent for the panels. Then you will have a order instead of a position to manipulate.
Maybe you can have a look at the DevExpress LAyoutControl? It helps us creating interfaces that always look good, no matter if we show or hide certain groups / panels. It even allows for run-time customization of the interface, if you want that!
You may try to organize them by coordinates i.e.: setting Top and Left. Unless your panels are aligned, this will always work (but it takes bit lot of work).
I had this problem and I found that the solution was to do this in FormCreate (or in a CMShowingChanged method of your frame):
MyPanel1.Align := alNone;
MyPanel2.Align := alNone;
MyPanel1.Align := alBottom;
MyPanel2.Align := alBottom;
Restore in the order that you need - this seemed to sort out the order visually.