为啥我释放左键后我的绘图消失了?

Posted

技术标签:

【中文标题】为啥我释放左键后我的绘图消失了?【英文标题】:Why my drawings disappear after I release my left click?为什么我释放左键后我的绘图消失了? 【发布时间】:2019-11-06 23:43:14 【问题描述】:

所以我试图在 OpenGL 中在我单击的点之间画线。如果我按下左键,绘图会在屏幕上显示,但如果我松开左键,它就会消失:

struct Vector 
    float x, y;
    Vector(float x = 0, float y = 0) : x(x), y(y) 

 last_mouse_pos;

void onInitialization() 
    glClearColor(0, 0, 0, 0); // A hatterszin beallitasa.
    glClear(GL_COLOR_BUFFER_BIT); // A kepernyo torlese, az uj hatterszinnel.


void onDisplay() 
    glutSwapBuffers();


Vector convertToNdc(float x, float y) 
    Vector ret;
    ret.x = (x - kScreenWidth / 2) / (kScreenWidth / 2);
    ret.y = (kScreenHeight / 2 - y) / (kScreenHeight / 2);
    return ret;


int i = 0;

void onMouse(int button, int state, int x, int y) 

    if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 
        glClear(GL_COLOR_BUFFER_BIT); 
        glutPostRedisplay(); 
    
    else if (button == GLUT_LEFT_BUTTON) 
        if (state == GLUT_DOWN) 
            i++;
            if (i == 1) last_mouse_pos = convertToNdc(x, y);
            if (i > 1) 
                Vector pos = convertToNdc(x, y);
                glBegin(GL_LINES);  
                glVertex2f(last_mouse_pos.x, last_mouse_pos.y);
                glVertex2f(pos.x, pos.y);
                glEnd();
                glutPostRedisplay();
                last_mouse_pos = pos; 
            
        
    

所以我做了2点,如果我按住左键,它会画线,如果我松开它,屏幕会变黑。如果我点击其他地方,现在我有 2 行,但前提是我按下左键。如果我释放,它会再次变黑。

【问题讨论】:

您可能收到了WM_ERASE 消息。 您的绘图仅发生在鼠标按下代码中。OpenGL 中的缓冲区被交换(在您的情况下:glutSwapBuffers).. 您没有绘制每一帧,因此在下一帧时它会被擦除呈现。 如果我已经换了...为什么又换回来了? 不要在你的输入回调中绘制,锁定一些状态并通过glutPostRedisplay()请求重新调用你的显示回调并在那里绘制。 【参考方案1】:

是的,你的方法有很多错误。在几乎所有情况下,您的绘图函数都应该是数据驱动的(即数据控制绘制的内容,而只有数据!)。大致如下:

// use this vector to store all of the point clicks
std::vector<Vector> points;

void onDisplay() 

  // now just render each vertex making up the lines
  glBegin(GL_LINES);
  for(auto p : points)
    glVertex2f(p.x, p.y);
  glEnd();

  glutSwapBuffers();

接下来,您将需要跟踪鼠标的状态,因此为了尽可能简单(您可能还想跟踪鼠标位置和其他按钮状态,但是这是一个最小的例子)

bool leftHeld = false;

接下来,您的鼠标功能现在将执行以下操作:

    按下左键时,向点数组添加一个新顶点。 释放左键时,更新数组中最后一个点的位置 当按下右键(并且没有按下左键)时,清除点数组。
void onMouse(int button, int state, int x, int y) 
  switch(button) 
  case GLUT_LEFT_BUTTON:
    
      leftHeld = state == GLUT_DOWN;
      if(leftHeld)
      
        points.push_back(convertToNdc(x, y)); // add new point
      
      else
        points.back() = convertToNdc(x, y); // update last point
    
    break;

  // on right click, empty the array
  // (but only if the left mouse button isn't currently pressed!)
  case GLUT_RIGHT_BUTTON: 
    if(!leftHeld && state == GLUT_DOWN)
      points.clear();
    break;
  
  glutPostRedisplay();

最后,如果您想在屏幕上单击并拖动时看到线条更新,您需要注册一个鼠标移动函数来更新数组中的最后一个点

// register with glutMotionFunc. 
// code updates last coordinate whilst mouse is moving, and
// the left button is held. 
void onMouseMove(int x, int y) 
  if(leftHeld)
  
    points.back() = convertToNdc(x, y);
  
  glutPostRedisplay();

【讨论】:

以上是关于为啥我释放左键后我的绘图消失了?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在取消 git 提交后我的更改消失了,我该如何恢复它们?

为啥我的自动释放对象没有被释放?

为啥订阅完成后我的数据会消失?

在帧写入循环中使用和不使用自动释放池的内存占用,为啥?

为啥我的 DirectX 程序无法识别我已经释放了转义键? (C++)

为啥我的 ModalViewController 没有释放?