JUCE - 制作新的 Window

JUCE - Making a New Window

在 JUCE 中使用可视化所见即所得编辑器制作 single-page 应用程序后,我在弄清楚如何调用新的 windows(在主 GUI 之外 window).我制作了一个测试应用程序,它只有一个我用可视化编辑器创建的最小主 GUI。它有一个按钮 "Make New Window." 我的目标是能够单击该按钮并弹出一个新的 window 并且这个新的 window 是一个 JUCE "GUI component," (又名,图形/可视 GUI 编辑器文件)。现在,我实际上已经 有点 实现了这一点,但是,它会抛出错误和断言,所以如果能得到一个非常简单的 step-by-step 教程会很棒。

我研究了 Projucer 自动创建的 main.cpp 文件,以了解他们如何创建 window。这是我所做的。

1) 在我的项目中,我添加了一个新的 GUI 组件(变成了 class)并命名为 "InvokedWindow." 2) 在我的主要 GUI 组件 class header 中,我添加了一个 InvokedWindow 类型的新作用域指针:ScopedPointer<InvokedWindow> invokedWindow; 3) 我在主 GUI 编辑器中创建了一个名为 "Make New Window" 的新按钮,并将其添加到处理程序代码中: newWindowPtr = new InvokedWindow; 这样,只要按下按钮,就会创建一个新的 object 类型的 InvokedWindow。 4) 在 InvokedWindow class 中,在构造函数中,在自动生成的代码之上,我添加了:

setUsingNativeTitleBar (true);
setCentrePosition(400, 400);
setVisible (true);
setResizable(false, false);

我从 JUCE 应用程序的主文件中得到的。

我还向这个新 window 添加了一个滑块,只是为了向它添加功能。

5) 我添加了一个重载函数来让我关闭 window:

void InvokedWindow::closeButtonPressed()
{
    delete this;
}

所以,现在当我 运行 应用程序并单击新建 window 按钮时,会弹出一个新的 window,但我得到一个断言:

/* Agh! You shouldn't add components directly to a ResizableWindow - this class
   manages its child components automatically, and if you add your own it'll cause
   trouble. Instead, use setContentComponent() to give it a component which
   will be automatically resized and kept in the right place - then you can add
   subcomponents to the content comp. See the notes for the ResizableWindow class
   for more info.

   If you really know what you're doing and want to avoid this assertion, just call
   Component::addAndMakeVisible directly.
*/

此外,我可以关闭 window 一次并点击主 GUI 中的按钮以创建新窗口的另一个实例,但第二次关闭它会导致错误:

template <typename ObjectType>
struct ContainerDeletePolicy
{
    static void destroy (ObjectType* object)
    {
        // If the line below triggers a compiler error, it means that you are using
        // an incomplete type for ObjectType (for example, a type that is declared
        // but not defined). This is a problem because then the following delete is
        // undefined behaviour. The purpose of the sizeof is to capture this situation.
        // If this was caused by a ScopedPointer to a forward-declared type, move the
        // implementation of all methods trying to use the ScopedPointer (e.g. the destructor
        // of the class owning it) into cpp files where they can see to the definition
        // of ObjectType. This should fix the error.
        ignoreUnused (sizeof (ObjectType));

        delete object;
    }
};

这让我有点头疼。我在想如果能够通过一个按钮创建一个新的 window 也不会太糟糕。我可以使用图形 GUI 编辑器编辑的新 window,但我自己无法完全弄清楚,尽管我确实尝试过。谁能 post step-by-step 指导以正确的方式做到这一点?我在 JUCE 论坛上做了 post 这个,但是由于我缺乏 GUI 编程,我无法理解 posted 的解决方案(我自己的错),所以我希望得到一个非常对此的简单指南。将不胜感激。谢谢。

我明白了。我需要创建:

  1. 一个新的 GUI 组件(记住,这是 JUCE 中的可视化编辑器)
  2. A class(我称它为 BasicWindow,基于 JUCE 演示代码)充当 shell 到 运行 这个新的 window 并保存 GUI组件。
  3. 一个 JUCE SafePointer,每当单击按钮时都会创建一个 BasicWindow 类型的新对象,并将属性设置为 window。

这是我的代码:

参考第 3 行)在按钮的处理程序部分内创建新的 window:

basicWindow = new BasicWindow("Information", Colours::grey, DocumentWindow::allButtons);

basicWindow->setUsingNativeTitleBar(true);
basicWindow->setContentOwned(new InformationComponent(), true);// InformationComponent is my GUI editor component (the visual editor of JUCE)

basicWindow->centreWithSize(basicWindow->getWidth(), basicWindow->getHeight());
basicWindow->setVisible(true);

参考第 2 行定义 BasicWindow 是什么的 .cpp 文件:

#include "../JuceLibraryCode/JuceHeader.h"

class BasicWindow : public DocumentWindow
{
private:
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BasicWindow)

public:
    BasicWindow (const String& name, Colour backgroundColour, int buttonsNeeded)
    : DocumentWindow (name, backgroundColour, buttonsNeeded)
    {
    }

    void closeButtonPressed() override
    {
        delete this;
    }
};

并参考第 1 行)制作 GUI 编辑器组件,这很容易做到。您只需在 JUCE 文件管理器中添加一个新文件即可。 "Add New GUI Component," 然后直观地添加所有元素和处理程序代码。

我最大的问题是我使用的是 JUCE ScopedPointer,所以在删除对象后,指向它的指针没有被设置回 NULL。 SafePointer 就是这样做的。如果需要更多解释,我很乐意提供帮助,因为这对于 GUI 开发不多的人来说太糟糕了 "under his belt."