在SFML中在屏幕上输入文本输入

问题描述 投票:4回答:2

所以我正在创建一个图形计算器。我有一个输入字符串s。从字符串中,我可以使用SFML对其进行图形化。我从MIN x坐标开始到MAX x坐标,从EvaluateString()方法获取相应的y,并将所有坐标转换为VertexArray v。我已经编写了我的方法和图形方法,并且一切运行良好。

但是,我有一个小问题。我想在屏幕上输入我的字符串,例如“sin(cos(tan(x)))”。我很难找到办法。我有点想通知它与事件TextEntered有关,但我仍然找不到任何完整的东西。

请建议我一个方法。

Sample graph

class Calculator{
public:
    void main();
private:
    WindowSize DefaultWindow;
    sf::RenderWindow window;
    Cartesian vertexX[2],vertexY[2];
    sf::Vertex axis[4];
    const double MAX = 10;
    const double MIN = -10;
    const double INCREMENT = 0.001;

};

int main(){ 
    DefaultWindow.Max = Cartesian(10,10);
    DefaultWindow.Min = Cartesian(-10,-10);
    DefaultWindow.plane.width=1500;
    DefaultWindow.plane.height=1500;

    // Set up x and y-axis
    vertexX[0] = Cartesian(-100,0);
    vertexX[1] = Cartesian(100, 0);
    vertexY[0] = Cartesian(0,-100);
    vertexY[1] = Cartesian(0,100);

    axis[0] = sf::Vertex(convertCartesiantoWindow(vertexX[0],DefaultWindow));
    axis[1] = sf::Vertex(convertCartesiantoWindow(vertexX[1],DefaultWindow));
    axis[2] = sf::Vertex(convertCartesiantoWindow(vertexY[0],DefaultWindow));
    axis[3] = sf::Vertex(convertCartesiantoWindow(vertexY[1],DefaultWindow));

    // Set up the window
    window.create(sf::VideoMode(1500, 1500), "Graphing calculator");

    // Input string
    string s = "sin(cos(tan(x)))";

    // Stack c contains all the Cartesian coordinate vertices
    // Cartesian is a struct which contains x and y coordinates
    Stack<Cartesian> c;

    sf::VertexArray v;

    // For a certain function in string s, I evaluate it 
    // and return the y_coordinate from the function EvaluateString (s, i)
    // Push each (x,y) evaluated in the Stack c
    for (double i = MIN; i <= MAX; i+= INCREMENT)
        c.Push(Cartesian(i,EvaluateString(s,i)));

    // v is VertexArray which contains all the vertices (x,y)
    v = plot(DefaultWindow, c);


    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {

            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
            }
        }
    }

    // Draw the graph
    window.clear(sf::Color::Black);
    window.draw(axis,4,sf::Lines);
    window.draw(v);
    window.display();
}
c++ sfml
2个回答
12
投票

作为@super suggest,使用库是一个很好的解决方案,肯定比我的好,但为了满足您的需求,我实现了一个超级基本的TextField类。

它可能有很多错误,但它可以让您了解如何实现该功能。

TextField只不过是一个包含文本的矩形。由于它将有一个sf::Text,它必须有一个sf::Font。另外,我限制它将包含的字符数。为了让我们在TextField内写,我们必须知道它是否被选中,即它是否具有焦点。所以,第一种方法可能是:

class TextField : public sf::Transformable, public sf::Drawable{
    private:
        unsigned int m_size;
        sf::Font m_font;
        std::string m_text;
        sf::RectangleShape m_rect;
        bool m_hasfocus;
};

我们需要这个类的构造函数:

class TextField : public sf::Transformable, public sf::Drawable{
    public:
        TextField(unsigned int maxChars) :
            m_size(maxChars),
            m_rect(sf::Vector2f(15 * m_size, 20)), // 15 pixels per char, 20 pixels height, you can tweak
            m_hasfocus(false)
        {
            m_font.loadFromFile("C:/Windows/Fonts/Arial.ttf"); // I'm working on Windows, you can put your own font instead
            m_rect.setOutlineThickness(2);
            m_rect.setFillColor(sf::Color::White);
            m_rect.setOutlineColor(sf::Color(127,127,127));
            m_rect.setPosition(this->getPosition());
        }

    private:
        unsigned int m_size;
        sf::Font m_font;
        std::string m_text;
        sf::RectangleShape m_rect;
        bool m_hasfocus;
};

我们还需要一些基本方法,我们想要在里面得到文本:

const std::string sf::TextField::getText() const{
    return m_text;
}

移动它,把它放在我们窗口的某个地方:

void sf::TextField::setPosition(float x, float y){
    sf::Transformable::setPosition(x, y);
    m_rect.setPosition(x, y);
}

这是一个棘手的问题。我们正在覆盖qazxsw poi的qazxsw poi qazxsw poi因为我们需要更新我们自己的setPosition

此外,我们需要知道一个点是否在框内:

method

很简单,我们使用sf::Transformablem_rect方法,已经在bool sf::TextField::contains(sf::Vector2f point) const{ return m_rect.getGlobalBounds().contains(point); }

设置(或取消设置)焦点在cointains

sf::RectangleShape

很容易。为了美观,我们还在聚焦时改变盒子的轮廓颜色。

最后,但并非最不重要的是,当收到输入(也称为)时,我们的TextField必须采取某种方式:

void sf::TextField::setFocus(bool focus){
    m_hasfocus = focus;
    if (focus){
        m_rect.setOutlineColor(sf::Color::Blue);
    }
    else{
        m_rect.setOutlineColor(sf::Color(127, 127, 127)); // Gray color
    }
}

我知道删除密钥检查有点脏。也许你可以找到更好的解决方案

就这样!现在TextField看起来像:

sf::Event

概念证明:

void sf::TextField::handleInput(sf::Event e){ if (!m_hasfocus || e.type != sf::Event::TextEntered) return; if (e.text.unicode == 8){ // Delete key m_text = m_text.substr(0, m_text.size() - 1); } else if (m_text.size() < m_size){ m_text += e.text.unicode; } }


-1
投票
main

这应该为输入创建一个sf :: Event :: TextEntered,为输出创建sf :: String

© www.soinside.com 2019 - 2024. All rights reserved.