【问题标题】:Tab system using panels使用面板的选项卡系统
【发布时间】:2023-12-28 11:49:01
【问题描述】:

我正在尝试使其显示面板可见并将其发送到前面,以便可以看到它并与之交互,就像这样。

private void SettingsButton_Click(object sender, EventArgs e)
{
    SettingsPanel.Visible = true;
    SettingsPanel.BringToFront();
}

问题是点击几个按钮后,它要么显示错误的面板,要么根本不显示。有没有办法解决这个问题?

编辑:在你们问之前,我正在使用 WinForms。

【问题讨论】:

  • 我假设您的面板上有控件。我还猜测您想有选择地控制面板的可见性及其包含的控件。您可能不想使用面板的 Z-Order 玩游戏。这控制了哪个控件是最前面的。作为一种猜测,如果您Bring to Front一个面板,它将隐藏它包含的控件。我要做的是更改面板的可见性并迭代面板的控件集合,从而更改每个控件的可行性。请记住,WinForms 只是 Win32 API 的一个薄包装器。
  • @FlyDog57 我一个字都听不懂,但是面板上还没有任何控件,整个面板消失了,不是控件。
  • 表单上的控件具有 Z 顺序。把它们想象成一副牌中的牌。您放下的第一张牌可能会被下一张牌部分覆盖。当您说 BringToFront 时,您是从原来的位置拿起一张卡片并放在顶部。 Visibility 属性控制控件是绘制还是隐藏。把所有东西都摆出来(x、y 和 z),然后玩一下能见度。在 WinForms 中,面板包含其他控件。但是,在幕后,一切都由 Windows 控制,并且所有控件都是对等的。这就是为什么我认为使用面板的 Z 顺序会搞砸事情
  • 哦,所有 WinForms 控件都有一个 Controls 属性,该属性表示该特定控件“包含”的控件集合。因此,您将控件放在面板中,如果您隐藏面板,我认为包含的控件不会被隐藏(但是,也许它们会被隐藏)。如果它们没有隐藏,您可以通过更改面板控件集合中控件的可见性来降低隐藏性
  • @Flydog57 我一点都不懂 :(

标签: c# winforms tabs panel


【解决方案1】:

好吧,我错了,WinForms 比我想象的要聪明。这是你可以做的测试。我不确定您要做什么,但这应该可以帮助您。首先,我们将构建一个小型 WinForms 应用程序。除了一个例外,我们不会设置放置在屏幕上的控件的任何属性:

  1. 创建一个新的 WinForms 应用程序
  2. 在设计器中,将一个面板(将命名为panel1)放在表单上
  3. 在属性窗格中,将 BorderStyle 设置为 FixedSingle(这是我们要设置的唯一属性)
  4. 将该面板复制两份(panel2panel3)。放置它们,使面板完全不重叠。
  5. 在每个面板上放置几个控件(我在每个面板上放置了标签(标签 1-3)和文本框(也是 1-3))
  6. 在每个面板旁边(安排得没有重叠)在表单上放置三个按钮(按钮 1-3),以便在视觉上,每个按钮都与类似编号的面板相关联
  7. 复制panel3 包括其包含的控件(这样您就可以得到panel4label4textbox4)。放置副本,使其与面板 3 显着重叠

现在我们将查看设计器为您的表单创建的代码。不要乱用这段代码(你可以,但如果你不知道自己在做什么,它可能会变得很糟糕——而且,我们保持这个简单)。

  1. 在解决方案资源管理器中,单击 Form1.cs 左侧未填充的三角形。请注意,它会旋转并变成实心。另请注意,显示 Form1.Designer.cs。这是一个通常隐藏的源文件,其中包含设计人员创建的与表单和您放置在其上的控件相对应的所有代码。
  2. 打开Form1.Designer.cs
  3. 单击Windows Form Designer generated code 旁边的小灰色加号图标
  4. 检查文件。请注意,您在设计器中执行的每个操作在 Designer.cs 文件中都有相应的代码行(或多或少)
  5. 查看其中一个面板的代码(比如panel1)。

看看它包括:

this.panel1.Controls.Add(this.textBox1);
this.panel1.Controls.Add(this.label1);
  1. 一直向下滚动到 Form1 代码,然后查看面板和按钮已添加到 Form 的 Controls 集合中:

喜欢:

this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.panel4);
this.Controls.Add(this.panel3);
this.Controls.Add(this.panel2);
this.Controls.Add(this.panel1);

注意顺序是颠倒的。顺序很重要,它为表单和表单上的控件设置 Z-Order(即,什么重叠什么)。

连接按钮

选择所有三个按钮并按<Enter>。这将打开 Form1.cs 文件并生成三个您可以填写的按钮单击处理程序。

将此代码用于三个按钮处理程序:

 private void button1_Click(object sender, EventArgs e) {
     var wasVisible = panel1.Visible;
     panel1.Visible = !wasVisible;
 }

 private void button2_Click(object sender, EventArgs e) {
     panel2.BringToFront();
 }

 private void button3_Click(object sender, EventArgs e) {
     panel3.BringToFront();
 }

第一个将切换第一个面板的可见性(我放入了一个额外的变量,以便您可以设置断点并查看发生了什么)。第二个把panel2带到最前面,改变它的Z-Order(之所以叫Z-Order,是因为屏幕上的位置是以X和Y为单位测量的,重叠位置与屏幕的“深度”有关,或 Z 坐标)。最后一个对panel3做同样的事情。

运行程序。

  • 当您按下第一个按钮时,第一个面板及其控件消失(这让我感到惊讶,WinForms 比我想象的更智能)
  • 当您按下第二个按钮时,似乎没有任何反应。这是因为panel2 唯一相交的是表单,而panel2 已经覆盖了表单,所以您看不到任何效果。 (而且因为 WinForms 比我想象的更聪明)
  • 当您按下第三个按钮时,panel2(和它的控件)会跳到控件堆栈的前面,覆盖panel4 的相交部分。

这是否有助于您了解 VisibleBringToFront() 的工作原理?

【讨论】:

    【解决方案2】:

    您所描述的内容类似于TabControl 替代方案。这是一个例子:

    您可以简单地通过使其可见并停靠以填充来管理当前面板。隐藏其他面板。

    public partial class FormTabsAlternative
        : Form
    {
        int         m_current = 0;
        List<Panel> m_tabs    = new List<Panel>();
    
        public FormTabsAlternative()
        {
            InitializeComponent();
    
            AddTab(pnl1);
            AddTab(pnl2);
            AddTab(pnl3);
            AddTab(pnl4);
    
            SetUpTabsAndButtons();
        }
    
        private void AddTab(Panel pnl)
        {
            m_tabs.Add(pnl);
    
            pnl.Dock = DockStyle.Fill;
        }
    
        private void OnLeftClick(object sender, EventArgs e)
        {
            if (m_current > 0)
            {
                m_current--;
    
                SetUpTabsAndButtons();
            }
        }
    
        private void OnRightClick(object sender, EventArgs e)
        {
            if (m_current < m_tabs.Count - 1)
            {
                m_current++;
    
                SetUpTabsAndButtons();
            }
        }
    
        private void SetUpTabsAndButtons()
        {
            for (int index = 0; index < m_tabs.Count; index++)
            {
                var panel     = m_tabs[index];
    
                panel.Visible = index == m_current;
            }
    
            btnLeft .Enabled = m_current > 0;
            btnRight.Enabled = m_current < m_tabs.Count - 1;
        }
    }
    

    【讨论】:

      最近更新 更多