1

In case of X11 display programming, I was wondering how to erase a structure from window once it is displayed. Let's say I want to draw a straight line, rectangle, and circle. However, I want the straight line to be vanished before rectangle is drawn and so on. Is there any function as such to do so?

Code:

#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <math.h>
#include "time.h"
#include "sys/time.h"

 // Global variables
 Display *display;
 Window  window;
 XSetWindowAttributes attributes;
 XGCValues gr_values;
 XFontStruct *fontinfo;
 GC gr_context;
 Visual *visual;
 int depth;
 int screen;
 XEvent event;
 XColor    color, dummy;

 main (argc, argv)
 char   *argv[];
 int     argc;
 {

 display = XOpenDisplay(NULL);
 screen = DefaultScreen(display);
 visual = DefaultVisual(display,screen);
 depth  = DefaultDepth(display,screen);
 attributes.background_pixel = XWhitePixel(display,screen);

 window = XCreateWindow( display,XRootWindow(display,screen),
                        200, 200, 1050, 1200, 5, depth,  InputOutput,
                        visual ,CWBackPixel, &attributes);
 XSetStandardProperties(display,window,"Welcome","Hi",None,NULL,0,NULL);
  XSelectInput(display,window,ExposureMask | KeyPressMask) ;
  fontinfo = XLoadQueryFont(display,"6x10");//6*10

   XAllocNamedColor(display, DefaultColormap(display, screen),"red",
                  &color,&dummy);

   gr_values.font = fontinfo->fid;
   gr_values.foreground = color.pixel;

   gr_context=XCreateGC(display,window,GCFont+GCForeground, &gr_values);

   // gr_context2=XCreateGC(display,window,GCFont+GCForeground, &gr_values);


 XFlush(display);
 XMapWindow(display,window);
 XFlush(display);
int i,j,a,b,h,w,angle1,angle2;
 while(1){
    XNextEvent(display,&event);

    switch(event.type){
    case Expose:
     //Straight line

        XDrawLine(display,window,gr_context,800,800, 400, 450);
        XFlush(display);
        usleep(50000);

    // Which function should I write here to make the line vanished??

     //Rectangle

        XDrawRectangle(display,window,gr_context,102,103, 200, 150);
        XFlush(display);
        usleep(50000);

     //Arc and Circle

      a = 600, b = 700;
      h = 100, w = 100;
      angle1 = 0, angle2 = 360*64;
      XDrawArc(display, window, gr_context, a-(w/2), b-(h/2), w, h, angle1,   angle2);
     XFlush(display);
        usleep(50000);

          break;

       case KeyPress: 
           XCloseDisplay(display); 
            exit(0);

         }
       }
     }

Updated Code: Concern - displays twice and then erases the first one

  #include <stdlib.h>
  #include <stdio.h>
  #include <X11/Xlib.h>
  #include <math.h>
  #include "time.h"
  #include "sys/time.h"



 // Global variables
 Display *display;
 Window  window;
 XSetWindowAttributes attributes;
 XGCValues gr_values;
 XFontStruct *fontinfo;
 GC gr_context;
 Visual *visual;
 int depth;
 int screen;
 XEvent event;
 XColor    color, dummy;

 main (argc, argv)
 char   *argv[];
 int     argc;
  { 
   display = XOpenDisplay(NULL);
   screen = DefaultScreen(display);
    visual = DefaultVisual(display,screen);
   depth  = DefaultDepth(display,screen);
   attributes.background_pixel = XWhitePixel(display,screen);

   window = XCreateWindow( display,XRootWindow(display,screen),
                        200, 200, 1050, 1200, 5, depth,  InputOutput,
                        visual ,CWBackPixel, &attributes);
   XSetStandardProperties(display,window,"Welcome","Hi",None,NULL,0,NULL);
   XSelectInput(display,window,ExposureMask | KeyPressMask) ;
   fontinfo = XLoadQueryFont(display,"6x10");
   XAllocNamedColor(display, DefaultColormap(display, screen),"cyan",
                  &color,&dummy);


   gr_values.font = fontinfo->fid;
   gr_values.foreground = color.pixel;
   gr_values.function   = GXxor;

   gr_context=XCreateGC(display,window,GCFont+GCForeground+GCFunction,   &gr_values);



   XFlush(display);
   XMapWindow(display,window);
   XFlush(display);
   int i,j,a,b,h,w,angle1,angle2;
    while(1){
    XNextEvent(display,&event);

    switch(event.type){
    case Expose:
    XDrawLine(display,window,gr_context,800,800, 400, 450);
    XFlush(display);
   usleep(500000);
     XDrawRectangle(display,window,gr_context,102,103, 200, 150);
    XFlush(display);
   usleep(500000);

         break;

    case KeyPress: 
         XCloseDisplay(display); 
         exit(0);

    }
  }
}
beginner
  • 411
  • 4
  • 14

1 Answers1

4

There is no direct way as X11 doesn't store objects that can be removed from a display list like higher level graphic libraries might support.

The simplest workaround would be to use XOR graphics.

Here is what should be changed in your code to achieve what you want using this approach:

***************
*** 38,40 ****

!    XAllocNamedColor(display, DefaultColormap(display, screen),"cyan",
                    &color,&dummy);
--- 38,40 ----

!    XAllocNamedColor(display, DefaultColormap(display, screen),"red",
                    &color,&dummy);
***************
*** 43,47 ****
     gr_values.foreground = color.pixel;
-    gr_values.function   = GXxor;

!    gr_context=XCreateGC(display,window,GCFont+GCForeground+GCFunction, &gr_values);

--- 43,46 ----
     gr_values.foreground = color.pixel;

!    gr_context=XCreateGC(display,window,GCFont+GCForeground, &gr_values);

***************
*** 66,68 ****
      // Which function should I write here to make the line vanished??
-         XDrawLine(display,window,gr_context,800,800, 400, 450);

--- 65,66 ----
***************
  • The drawing color is changed from red to cyan for the xor rendering to stay red when on a white background.

  • The graphic context now includes the GXxor function.

  • A second drawing of the line with the very same arguments is added after the delay. This second call "neutralize" the previous one therefore the screen reverts to what it was originally.

Alternatively, you can use double buffering but that imply you need to redraw everything but the deleted object(s) on the alternate buffer.

jlliagre
  • 29,783
  • 6
  • 61
  • 72
  • Thanks Jilliagre. I made the changes, but the output is somehow peculiar. Just to make sure I got your reply rightly, I simply changed the color to cyan, added the line gr_values.function=GXxor and added GCFunction in the gr_context assignment. The sequence of o/p - 1.Rectangle 2.Straightline after the delay 3. both vanished 4.Again rectangle and then straight-line on screen 4. rectangle vanished and straight-line is still there. Why both are again coming for the second time? – beginner Jul 12 '15 at 02:15
  • Double check your code. It looks like there are extra drawing instructions. If you can't find where the issue is, append your whole updated code at the end of your question. – jlliagre Jul 12 '15 at 11:53
  • Hi Jlliagre, I've updated the new code. Could you please check once and let me know if everything looks fine as per your suggestion? Thanks. – beginner Jul 13 '15 at 02:49
  • In order to erase a graphic primitive using XOR drawing, you need to draw it twice but you do it only once in the updated code. A second issue is parts of the window look to be temporarily hidden by another X11 window, the reason why you got more than one expose event. That should explain why the rectangle and the line had a different rendering after a while despite being drawn the same way. You might want to add ` XClearWindow(display, window);` at the beginning of your `Expose` case block to get a better behavior. – jlliagre Jul 13 '15 at 06:47
  • I checked with XClearWindow() and used XDraw() twice. Changes I made, put XClearWindow(display, window) just at the beginning of Expose and used XDrawRectangle() and XDrawLine() twice with the same arguments. Now, I am getting the old activities four times and then the first object, i.e. rectangle gets erased. – beginner Jul 13 '15 at 07:19
  • If you draw the line and rectangle twice, both will be eventually erased. Not sure about what you mean with "old activities four times" but I guess some regions of your window are being obscured by other windows for some reason, explaining the multiple expose events issue. The latter is a different problem that deserve a different question. – jlliagre Jul 13 '15 at 08:07
  • Old activities means the output I was getting after running the updated code I mentioned earlier. So, now what I'm getting is rectangle and line 4 times and then rectangular vanishes. So, that's what I was pointing. – beginner Jul 13 '15 at 08:36
  • You seem to be using a graphic environment that temporarily obscures parts of your window. If you believe drawing twice a graphic primitive in XOR mode doesn't work in your case, provide more clues about what your graphic environment is for us to be able to reproduce what you observe. – jlliagre Jul 13 '15 at 11:10
  • Graphic environment - well, I'm using a mac where I'm running X11 using XQuartz. Graphics driver - Intel iris pro and Nvidia GTM. Is this the info you are looking for? – beginner Jul 13 '15 at 19:37
  • It is, although I have no mac to reproduce then. In any case, you should at least "pack" the multiple expose events you get by filtering them off all but the last one. Have a look to http://stackoverflow.com/questions/12871071/x11-how-to-delay-repainting-until-all-events-are-processed for a way to do it. – jlliagre Jul 13 '15 at 19:46
  • Okay. Thanks. I"ll check that. – beginner Jul 13 '15 at 20:46